More is less

Vendredi 1er septembre 2017

Yield

Dans python, ma fonction préférée est yield. Comme moi, c'est une feignasse. Elle attend qu'on l'invoque, brandit son résultat et retourne dans son terrier.

Fonctions range

Avec yield on pourrait redéfinir la fonction range ainsi :

def range(begin, end, step):
	x = begin
	while x < end:
		yield x
		x += step

Mais range ne produit que des séquences de nombres entiers. Alors que notre fonction ci-dessus peut aussi bien accepter des paramètres flottants(float) et retourner des séquences de flottants.

def frange(begin, end, step):
	x = begin
	while x < end:
		yield x
		x += step

Exemple :

>>> l = list(range(1,.01))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'float' object cannot be interpreted as an integer
>>> l = frange(0, 1, 0.1)
>>> print([round(x, 1) for x in l])
[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]

Note : le manège avec round(x, 1) for ... est là pour éviter l'affichage avec un paquet de décimales

Extraire des couples

Il arrive qu'on ait besoin d'extraire les éléments d'une liste deux par deux.

Exemple : la méthode create_line de la classe Canvas de tkinter, admet un nombre indéfini de paramètres x1, y1, x2, y2, .... Sa signature est :

def create_line(self, *args, **kw)

On voudrait faire un traitement aux coordonnées des points avant l'appel de la fonction.

Notre fonction génératrice pourrait être définie par :

def couple(l):
	it = iter(l)
	while True: yield next(it), next(it)

A chaque appel de couple, yield founit un couple. On pourrait alors écrire :

>>> l = list(range(8))
>>> print([c for c in couple(l)])
[(0, 1), (2, 3), (4, 5), (6, 7)]
>>> 

Remarque

On pouvait utilser zip et les tranches de liste [start:stop:step] plus exactement l[0::1] et l[1::2]

>>> [c for c in zip(l[0::2], l[1::2])]
[(0, 1), (2, 3), (4, 5), (6, 7)]

L'avantage des générateurs c'est leur caractère fainéant. Un autre avantage, on n'a pas besoin d'aplatir les tuples.

Remarque

Subtilité de la langue françoise : on écrit «fainéant» mais «feignasse».


Réalisé avec Qlam - LGPL