Module collections
En complément des types de données natifs (dict, list, set, tuple), le module collections propose plusieurs types supplémentaires :
namedtuple: génère un tuple dont les éléments sont accessibles par un nomdeque: file doublement terminée, permettant des ajouts et retraits rapides aux deux extrémitésOrderedDict: dictionnaire qui conserve l’ordre d’insertion des clésdefaultdict: dictoinnaire avec une valeur par défaut pour les clés manquantesCounter: compteur servant à dénombrer les occurrences d’éléments
namedtuple
Un tuple classique peut représenter un ensemble immuable, par exemple les coordonnées d’un point :
>>> t = (1, 2)
Cependant, lire (1, 2) ne permet pas de comprendre qu’il s’agit d’un point. namedtuple vient résoudre ce problème :
In [1]: from collections import namedtuple
In [2]: Point = namedtuple('Point', ['x', 'y'])
In [3]: p = Point(1, 2)
In [4]: p
Out[4]: Point(x=1, y=2)
In [5]: p.x
Out[5]: 1
In [6]: p.y
Out[6]: 2
De même, pour représenter un cercle avec son centre et son rayon :
# namedtuple('Nom', [liste d'attributs])
Cercle = namedtuple('Cercle', ['x', 'y', 'r'])
Cette structure est également utile dans un jeu de cartes, où chaque carte est définie par sa couleur et sa valeur.
deque
L’accès par indice est rapide avec une list, mais les insertions et suppressions sont lentes car le stockage est linéaire. deque est optimisé pour ces opérations et cnovient parfaitement aux files et aux piles :
from collections import deque
d = deque()
d.append('a') # ajout à droite
d.appendleft('b') # ajout à gauche
print(d) # deque(['b', 'a'])
d.pop() # retire 'a'
d.popleft() # retire 'b'
OrderedDict
Avec un dictionnaire classique, l’ordre des clés n’est pas garanti. OrderedDict conserve l’ordre d’insertion :
In [29]: from collections import OrderedDict
In [30]: d = dict([('a', 1), ('b', 2), ('c', 3)])
In [31]: d
Out[31]: {'a': 1, 'b': 2, 'c': 3} # ordre quelconque
In [32]: od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
In [33]: od
Out[33]: OrderedDict([('a', 1), ('b', 2), ('c', 3)]) # ordre préservé
Attention : l’ordre est celui de l’insertion, et non celui des clés elles-mêmes :
In [35]: od['z'] = 1
In [36]: od['y'] = 2
In [37]: od['x'] = 3
In [38]: od.keys()
Out[38]: odict_keys(['a', 'b', 'c', 'z', 'y', 'x'])
defaultdict
Supposons une liste de valeurs [11, 22, 33, 44, 55, 66, 77, 88, 99, 90]. On souhaite placer les valeurs supérieures à 66 dans une clé 'k1' et les valeurs inférieures à 66 dans 'k2'. Avec un dictionnaire standard :
valeurs = [11, 22, 33, 44, 55, 66, 77, 88, 99, 90]
mon_dico = {}
for v in valeurs:
if v > 60:
if 'k1' in mon_dico:
mon_dico['k1'].append(v)
else:
mon_dico['k1'] = [v]
elif v < 60:
if 'k2' in mon_dico:
mon_dico['k2'].append(v)
else:
mon_dico['k2'] = [v]
print(mon_dico)
Avec defaultdict, le code devient plus simple :
from collections import defaultdict
valeurs = [11, 22, 33, 44, 55, 66, 77, 88, 99, 90]
mon_dico = defaultdict(list)
for v in valeurs:
if v > 60:
mon_dico['k1'].append(v)
elif v < 60:
mon_dico['k2'].append(v)
print(mon_dico)
# defaultdict(<class 'list'>, {'k1': [66, 77, 88, 99, 90], 'k2': [11, 22, 33, 44, 55]})
Pour définir une valeur par défaut qui n’est pas un type (ex. une constante), on utilise une lambda :
In [39]: from collections import defaultdict
In [40]: dd = defaultdict(lambda: 'N/A')
In [41]: dd['key1'] = 'abc'
In [43]: dd['key1']
Out[43]: 'abc'
In [44]: dd['key2'] # clé inexistante
Out[44]: 'N/A'
Counter
Counter permet de compter les occurrences d’éléments dans un itérable :
In [45]: from collections import Counter
In [46]: c = Counter('adfasdfawrsadfadfasdfzcv')
In [47]: print(c)
Counter({'a': 6, 'f': 5, 'd': 5, 's': 3, 'w': 1, 'c': 1, 'v': 1, 'r': 1, 'z': 1})
In [48]: print(c['a'])
6
Module time
Pour toutes les opérations temporelles, on importe le module time.
# Méthodes courantes
1. time.sleep(secs) # suspend l'exécution pendant secs secondes
2. time.time() # retourne le timestamp actuel (secondes depuis 1970-01-01)
En Python, le temps se représente sous trois formes :
- Timestamp : nombre de secondes écoulées depuis le 1er janvier 1970.
- Chaîne formatée : par exemple
'1990-12-06'. - Struct_time : tuple de 9 éléments (année, mois, jour, heure, minute, seconde, jour de la semaine, jour dans l’année, heure d’été).
Symboles de formatage courants :
%y année sur 2 chiffres (00-99)
%Y année sur 4 chiffres (0000-9999)
%m mois (01-12)
%d jour du mois (01-31)
%H heure en format 24h (00-23)
%I heure en format 12h (01-12)
%M minutes (00-59)
%S secondes (00-59)
%a nom abrégé du jour de la semaine
%A nom complet du jour
%b mois abrégé
%B mois complet
%c date et heure locales
%j jour dans l’année (001-366)
%p AM/PM
%U numéro de semaine (dimanche premier jour) (00-53)
%w jour de la semaine (0=dimanche, 6=samedi)
%W numéro de semaine (lundi premier jour) (00-53)
%x date locale
%X heure locale
%Z fuseau horaire
%% le caractère %
Exemples des trois formats
In [49]: import time
In [50]: time.time()
Out[50]: 1539398412.6536071 # timestamp
In [51]: time.strftime('%Y%m%d %X')
Out[51]: '20181013 10:40:40' # chaîne formatée
In [52]: time.localtime()
Out[52]: time.struct_time(tm_year=2018, tm_mon=10, tm_mday=13, tm_hour=10, tm_min=40, tm_sec=47, ...)
Conversions entre formats
Timestamp → struct_time :
In [6]: time.localtime(1500000000)
Out[6]: time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, tm_sec=0, ...)
struct_time → timestamp :
In [7]: time.mktime(time.localtime(1500000000))
Out[7]: 1500000000.0
struct_time → chaîne formatée :
In [12]: time.strftime('%Y%m%d %H:%M:%S', time.localtime(1500000000))
Out[12]: '20170714 10:40:00'
Chaîne formatée → struct_time :
In [14]: time.strptime('20170714 10:40:00', '%Y%m%d %H:%M:%S')
Out[14]: time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, ...)
Autres raccourcis :
In [16]: time.asctime(time.localtime(1500000000))
Out[16]: 'Fri Jul 14 10:40:00 2017'
In [17]: time.ctime(1500000000)
Out[17]: 'Fri Jul 14 10:40:00 2017'
Exercice
Calculer le temps écoulé depuis le 1er janvier 2008 00:00:00 jusqu’à maintenant :
import time
debut = time.strptime('2008-1-1 00:00:00', '%Y-%m-%d %H:%M:%S')
maintenant = time.localtime(time.time())
print('Depuis 2008 : %d ans %d mois %d jours %d heures %d minutes %d secondes' % (
maintenant.tm_year - debut.tm_year,
maintenant.tm_mon - debut.tm_mon,
maintenant.tm_mday - debut.tm_mday,
maintenant.tm_hour - debut.tm_hour,
maintenant.tm_min - debut.tm_min,
maintenant.tm_sec - debut.tm_sec
))
Module random
# Nombres à virgule flottante aléatoires
random.random() # entre 0.0 et 1.0
random.uniform(1, 3) # entre 1 et 3
# Nombres entiers aléatoires
random.randint(1, 5) # entier compris entre 1 et 5 inclus
random.randrange(1, 10, 2) # entier impair entre 1 et 9
# Sélection aléatoire
random.choice([1, '23', [4,5]]) # un élément au hasard
random.sample([1, '23', [4,5]], 2) # deux éléments distincts
# Mélange d'une liste
item = [1, 3, 5, 7, 9]
random.shuffle(item) # mélange sur place
print(item)
Exercice : génération de code de vérification
import random
def generer_code(longueur=5):
code = ''
for _ in range(longueur):
chiffre = random.randint(0, 9)
lettre = chr(random.randint(65, 90)) # lettre majuscule
caractere = random.choice([chiffre, lettre])
code += str(caractere)
return code
print(generer_code())
Module os (interface avec le système d’exploitation)
os.makedirs('repertoire1/repertoire2') # création récursive
os.removedirs('repertoire1') # suppression récursive des répertoires vides
os.mkdir('repertoire') # création d’un seul répertoire
os.rmdir('repertoire') # suppression d’un répertoire vide
os.listdir('chemin') # liste des fichiers et dossiers
os.remove('fichier') # suppression d’un fichier
os.rename('ancien', 'nouveau') # renommage
os.stat('chemin/fichier') # informations sur le fichier
os.system('commande shell') # exécution d’une commande (affichage direct)
os.popen('commande').read() # exécution et récupération du résultat
os.getcwd() # répertoire de travail courant
os.chdir('autre_repertoire') # changement de répertoire
# Sous-module os.path
os.path.abspath('chemin') # chemin absolu normalisé
os.path.split('chemin') # (répertoire, fichier)
os.path.dirname('chemin') # répertoire
os.path.basename('chemin') # nom du fichier
os.path.exists('chemin') # True si le chemin existe
os.path.isabs('chemin') # True si chemin absolu
os.path.isfile('chemin') # True si fichier existant
os.path.isdir('chemin') # True si dossier existant
os.path.join('rep1', 'rep2', 'fichier') # assemblage de chemins
os.path.getatime('chemin') # dernier accès
os.path.getmtime('chemin') # dernière modification
os.path.getsize('chemin') # taille en octets
Attributs supplémentaires :
os.sep # séparateur de chemin ('\\' sous Windows, '/' sous Linux)
os.linesep # fin de ligne ('\r\n' sous Windows, '\n' sous Linux)
os.pathsep # séparateur de chemins (';' Windows, ':' Linux)
os.name # nom du système ('nt' pour Windows, 'posix' pour Linux)
Module sys (interaction avec l’interpréteur Python)
sys.argv # liste des arguments de la ligne de commande (premier = nom du script)
sys.exit(n) # quitte le programme (0 = succès, autre = erreur)
sys.version # version de l’interpréteur
sys.path # liste des chemins de recherche des modules
sys.platform # nom de la plateforme (ex : 'win32', 'linux')