En Python, les collections sont généralement générées en inclusion (je pense).
Cependant, quand cela devient un peu compliqué, la notation d'inclusion est difficile à lire.
#Inclure de force la liste Fizz Buzz
fb = ["Fizz Buzz" if i % 15 == 0
else "Fizz" if i % 3 == 0
else "Buzz" if i % 5 == 0
else i
for i in range(30)]
Dans ce cas, il est plus facile de lire en écrivant une instruction for.
Cependant, le style d'écriture consistant à effectuer de petits changements tout en exposant l'objet avant l'initialisation est quelque peu coupable (lorsque la préférence fonctionnelle est forte).
fb = []
for i in range(30):
if i % 15 == 0:
fb.append("Fizz Buzz")
elif i % 3 == 0:
fb.append("Fizz")
elif i % 5 == 0:
fb.append("Buzz")
else:
fb.append(i)
Que faire?
Il est possible de définir un générateur avec rendement et de créer une collection basée sur celui-ci.
def _fb():
for i in range(30):
if i % 15 == 0:
yield "Fizz Buzz"
elif i % 3 == 0:
yield "Fizz"
elif i % 5 == 0:
yield "Buzz"
else:
yield i
fb = list(_fb)
↑ n'est pas mal, mais après avoir défini le générateur, la procédure pour l'assigner à une variable via la fonction de liste est compliquée.
De plus, si vous oubliez d'en faire une liste et de recevoir l'itérateur directement sous forme de variable, cela peut être un foyer de bogues.
Je veux que la définition utilisant yield soit interprétée comme la définition de la liste telle quelle.
Ceci peut être réalisé en utilisant un décorateur.
def comprehension(collector):
def ret(func):
return collector(func())
return ret
#La liste est affectée à la variable "fb" en exécutant ce qui suit.
@comprehension(list)
def fb():
for i in range(30):
if i % 15 == 0:
yield "Fizz Buzz"
elif i % 3 == 0:
yield "Fizz"
elif i % 5 == 0:
yield "Buzz"
else:
yield i
Le premier matériel source est le décorateur appelé collection dans la bibliothèque appelée funcy. Transformez la fonction de générateur en une fonction qui renvoie une liste. Avec cela, Fizz Buzz peut être écrit comme suit:
from funcy import collecting
@collecting
def _fb():
for i in range(30):
if i % 15 == 0:
yield "Fizz Buzz"
elif i % 3 == 0:
yield "Fizz"
elif i % 5 == 0:
yield "Buzz"
else:
yield i
fb = _fb()
Cependant, il est difficile de définir la fonction une fois.
Raquette [pour / list](https://docs.racket-lang.org/reference/for.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for%2Flist% J'ai pensé que si je pouvais écrire quelque chose comme 29% 29), j'ai trouvé une solution qui ne renvoie pas de fonction dans le décorateur.
Recommended Posts