Xavier Lamorlette

Python : éléments de syntaxe avancée

Sommaire :

Extraction et empaquettement des arguments

Extraction des arguments : unpacking

Pour passer des arguments à une fonction, on peut utiliser * sur une liste (souvent nommée *args), ou ** sur un dictionnaire (souvent nommé **kwargs).

def toto(a, b): ...

args = (1, 2)
toto(*args)

kwargs = {'b': 2, 'a': 1}
toto(**kwargs)

Empaquettement des arguments : packing

À l'inverse, on peut regrouper les arguments d'une fonction dans une liste et un dictionnaire :

def toto(*args, **kwargs): ...
    print(f"positional arguments: {args}")
    print(f"keyword arguments: {kwargs}")

toto(1, 2, tata=3, titi=4)

→
positional arguments: (1, 2)
keyword arguments: {'tata': 3, 'titi': 4}

Générateurs

Une fonction qui utilise yield est une fonction génératrice. Elle retourne un générateur.
Lorsque l'on demande une valeur au générateur, il exécute son code jusqu'au prochain yield :

def arithmetic_generator(n_max):
    x = 0
    n = 0
    while n <= n_max:
       yield x
       x += 12
       n += 1

for x in arithmetic_generator(10):
    …

Pour demander une valeur au générateur, on peut aussi utiliser next.
Il faut alors rattraper l'exception StopIteration qui est levée lorsque le générateur atteint la fin de sa fonction.

Expression génératrice

Utiliser des parenthèses à la place des crochets d'une compréhension de liste crée un générateur qui évite le stockage dans une liste temporaire :

tata = (item for item in toto if condition(item))
for item in tata:
   …

Classe itérable

Pour rendre une classe itérable, le plus simple est d'implémenter la méthode __iter__() comme une fonction génératrice :

class A:
    def __iter__(self):
        …
        yield …

Gestionnaires de contexte

Un gestionnaire de contexte est une classe implémentant les méthodes __enter__() et __exit__() :

class File():
    def __init__(self, filename):
        self._file = open(filename, 'w')

    def __enter__(self):
        return self._file

    def __exit__(self, type, value, traceback):
        self._file.close()

with File("toto.txt") as file:
    file.write("toto")
from time import time

class Timer():
    def __init__(self, name):
        self._name = name

    def __enter__(self):
        self._start = time()

    def __exit__(self, type, value, traceback):
        milliseconds = (time() - self._start) * 1000
        print(f"{self._name}: {milliseconds} ms")

with Timer("toto"):
    …

@contextmanager

On peut créer un gestionnaire de contexte avec @contextmanager et un yield :

from contextlib import contextmanager
from time import time

@contextmanager
def timer(name):
    start = time()
    yield
    milliseconds = (time() - start) * 1000
    print(f"{name}: {milliseconds} ms")

with timer("toto"):
    …

La dernière mise à jour de cette page date de mai 2024.

Le contenu de ce site est, en tant qu'œuvre originale de l'esprit, protégé par le droit d'auteur.
Pour tout commentaire, vous pouvez m'écrire à xavier.lamorlette@gmail.com.