www.jchr.be - GPL2
Fichier d'exemples disparates de bidouilles (non orientées objet) écrites en python pour illustrer la page de présentation de python.
Les listes ne sont pas des tableaux comme il en existe en C, mais il est possible de les initialiser comme tels. t=[[0]*3]*4 donne [[0,0,0], [0,0,0], [0,0,0], [0,0,0]], soit une liste de quatre sous-listes de trois éléments. t[2][1]=7 devrait assigner la valeur 7 au 2e élément de la 3e liste, mais print t donne [[0,7,0], [0,7,0], [0,7,0], [0,7,0]], ce qui montre que python se souvient qu'il a cloné la sous-liste [0,0,0], devenue [0,7,0].
On peut néanmoins construire une liste de quatre sous-listes de trois éléments initialisés à 0 où chaque élément est individualisé:
#! /usr/bin/python
# -*- coding: latin-1 -*-
t=[]
for i in range(4):
t+=[[]] # ajoute quatre fois une sous-liste vide:[[],[],[],[]]
for j in range(3):
t[i]+=[0] # ajoute trois éléments '0' à chacune des quatre sous-listes vides
t[2][1]=9 # 9 est assigné à un endroit précis
print t # ...et rien que là
Une autre possiblilité est de passer par les tuples:
#! /usr/bin/python # -*- coding: latin-1 -*- t=[(0,)*3]*4 # (virgule!) donne une liste de quatre tuples: [(0,0,0),(0,0,0),(0,0,0),(0,0,0)] for i in range(4): t[i]=list(t[i]) # chaque tuple est transformé en liste t[2][1]=9 # 9 est assigné au deuxième élément de la troisième sous-liste print t # ...et rien que là. On a gagné deux lignes de code
Mais pour un tableau à 3, 4, n... dimensions? Il faut construire un tuple de tuples de tuples... en tenant compte du fait que ((0,)*3)*2 donne (0,0,0,0,0,0) et non ((0,0,0),(0,0,0)): il faut passer par des listes. Pour trois dimensions:
#! /usr/bin/python
# -*- coding: latin-1 -*-
t=(0,)*3
t=tuple([t]*4) # [(0,0,0),(0,0,0),...] transformé en ((0,0,0),(0,0,0),...)
t=[t]*5
for i in range(len(t)):
t[i]=list(t[i]) # [((0,0,0),(0,0,0)... transformé en [[(0,0,0),(0,0,0)...
for j in range(len(t[i])):
t[i][j]=list(t[i][j]) # [[(0,0,0),(0,0,0)... transformé en [[[0,0,0],[0,0,0]...
print t,"\n"
t[0][2][1]=9
print t
Le premier exemple est alors plus simple
! /usr/bin/python
# -*- coding: latin-1 -*-
t=[]
for i in range(5):
t+=[[]] # ajoute 5 fois une sous-liste vide:[[],[],[],[],[]]
for j in range(4):
t[i]+=[[]] # ajoute 4 fois une sous-sous-listes vides [] à chacune des 5 sous-listes vides
for k in range(3):
t[i][j]+=[0] # ajoute 3 éléments 0 à chacune des sous-sous-listes vides
t[0][2][1]=9 # 9 est assigné à un endroit précis
print t # ...et rien que là
Si on veut initialiser un tableau dont on ne sait pas a priori combien il aura de "dimensions", on peut utiliser la récursivité. Le principe est de passer un tuple qui reprend le nombre d'éléments de chaque dimension (on passe et on récupère un tuple en paramètre en le préfixant d'un astérisque).
#! /usr/bin/python
# 2008.02.20 - www.jchr.be - GPL2
# initialise une liste de x listes de y listes... de n éléments
def tableau(*dim):
tab=[]
if len(dim):
for i in range(dim[0]):
tab+=[0]
if len(dim)>1: # si le tableau a plus d'une dimension...
tab[i]=tableau(*dim[1:]) # ... on traite la dimension suivante
return tab
tup=input("x,y... ,n: ") # "n," pour une seule dimension
print tableau(*tup)
Le concept de liste est finalement assez différent de celui du tableau. Il est plus souple parce qu'une liste peut contenir toute sorte d'éléments, et par exemple elle-même:
>>> li=['a','b'] >>> li+=[li] >>> li ['a', 'b', [...]] >>> li[2] ['a', 'b', [...]] >>> li[2][2] ['a', 'b', [...]] >>> li[2][2][2][2][2][2][2][2][2][2][2][2][2] ['a', 'b', [...]]
Il reste à voir à quoi cela peut servir... Pour les tableaux et matrices, utilisez plutôt les modules externes Numeric, numarray ou mieux: numpy
Pour filtrer une liste déjà existante, on pourrait copier chaque élément sous condition dans une autre. Pour éviter la création d'une variable supplémentaire, on peut la parcourir à l'envers et enlever tout ce qui doit l'être.
#! /usr/bin/python
liste=range(100) # liste des entiers 0 à 99
lon=len(liste)
for i in range(lon-1,-1,-1): # parcours inverse
if liste[i] %2 ==0: # pair?
liste.pop(i) # supprimé
print liste
Malheureusement, le temps pris par l'élimination d'un élément est plus long que l'ajout à une liste (cas d'une seconde variable) et augmente encore avec la taille de la liste:
#! /usr/bin/python
import time
for j in range(5,15):
liste=range(10000*j)
longueur=len(liste)
liste2=[]
t=time.time()
for i in range(longueur):
if liste[i]%2==0:
liste2+=[liste[i]]
print time.time()-t,
liste=range(10000*j)
longueur=len(liste)
t=time.time()
for i in range(longueur-1,-1,-1): # parcours inverse
if liste[i]%2==0:
liste.pop(i)
print "- ",time.time()-t
raw_input("Une touche pour terminer")
Fichiers pour lesquels on utilise un pointeur pour accéder à un endroit particulier du fichier.
#! /usr/bin/python
# -*- coding: latin-1 -*-
"""Exemple d'utilisation de fichier random access - 2007-01-18 - www.jchr.be - GPL-2"""
fd=file("fichier.txt",'w')
fd.seek(10) # se positionne le pointeur sur le 11ème octet à partir du début
fd.write("Spam") # y écrit le texte (attention: la position du pointeur devient 14)
fd.seek(-10,1) # remonte de 10 octets ("-10") à partir de la position actuelle ("1")
fd.write("Eggs")
fd.close()
fd=file("fichier.txt")
fd.seek(0,2) # longueur du fichier: décalage 0 par rapport à la fin du fichier ('2')
eof=fd.tell()
fd.seek(0) # début du fichier: décalage 0 par rapport au début du fichier
for i in range(eof):
print fd.read(1) # imprime la lecture d'un caractère, et déplace le pointeur
fd.close()
Sous-module os.path
Le travail sur les répertoires et fichiers est possible à partir du module interne os.
Pour déterminer le chemin complet du script appelé, il faut en plus utiliser le module sys:
#! /usr/bin/python # -*- coding: latin-1 -*- # permet les accents dans le script import sys, os script= sys.argv[0] # le premier element de argv est le nom du script, les suivants: parametres chemin= os.path.abspath(script) # chemin + nom du script repertoire= os.path.dirname(chemin) # retourne la partie chemin print repertoire
Le script suivant détermine le répertoire par défaut (le plus souvent /home/votre_ID) et place tout ce qui s'y trouve dans la liste dossier. Une boucle permet ensuite de passer en revue tout ce qu'il y a dans la liste et reconstitue le chemin entier de l'objet (os.sep permet la compatibilité avec les différents systèmes:'/' pour Unix, '\' pour Microsoft, ':' pour Mac). Pour autant que le test détermine avec os.path.isfile() que l'objet est un fichier, celui-ci est affiché.
#! /usr/bin/python
# -*- coding: latin-1 -*- # permet les accents dans le script
import os
chemin=os.getcwd() # ! il ne s'agit pas nécessairement du répertoire du script
dossier=os.listdir(chemin)
for nom in dossier: # pour chaque chose rencontrée dans un répertoire
element= chemin+os.sep+nom # le chemin complet est composé
if os.path.isfile(element): # teste si element est un fichier
print element
De la même manière, os.path.isdir() permet de vérifier qu'on est en présence d'un répertoire. Il est exploité ci-dessous dans une fonction récursive: chaque répertoire recense et traite ses sous-répertoires.
#! /usr/bin/python
# -*- coding: latin-1 -*- # permet les accents dans le script
import sys,os # importe les modules system et operating system
def entrer(dans,n): # définition de la fonction
repertoires=os.listdir(dans)
for nom in repertoires:
nouveau=dans + os.sep + nom # addition du chemin complet
if os.path.isdir(nouveau): # teste s'il s'agit d'un répertoire
print " "*n+nouveau # n est la profondeur de récursion, convertie en espaces
entrer(nouveau,n+1) # recherche les éléments du répertoire (récursion)
chemin=os.path.dirname(os.path.abspath(sys.argv[0])) # chemin complet du script
entrer(chemin,0)
raw_input("Une touche pour quitter...")