J'ai lu la documentation de python et j'ai découvert Iterator, Generator, Decorator, etc.
http://docs.python.jp/2/tutorial/classes.html#iterator
(Commencez à citer)
Ces méthodes d'accès sont claires, concises et pratiques. L'utilisation d'itérateurs est répandue dans Python et apporte l'unité. Dans les coulisses, l'instruction for
appelle l'objet conteneur ʻiter (). Cette fonction renvoie un objet itérateur avec la méthode
next ()définie. La méthode
next ()accède aux éléments du conteneur un par un. Lorsqu'il n'y a plus d'éléments auxquels accéder dans le conteneur,
next ()lève une exception
StopIterationet met fin à la boucle for. L'exemple suivant montre comment cela fonctionne réellement. (Omis) Une fois que vous avez vu le mécanisme derrière le protocole itérateur, il est facile d'ajouter un comportement itératif à votre classe. Assurez-vous de définir la méthode
iter ()pour renvoyer un objet avec la méthode
next ()`. Si la classe elle-même définit «next ()», «iter ()» peut simplement renvoyer «self».
(Fin de la citation)
Si vous voulez vous faciliter la tâche, vous pouvez définir une classe avec la méthode __iter__ ()
et la méthode next ()
, et lancer une exception de StopIteration
lorsque la condition de terminaison est satisfaite.
Il semble que l'instance d'Iterator puisse être utilisée telle quelle dans l'instruction for
.
J'ai écrit un FizzBuzzIterator avec des spécifications similaires en faisant référence à la fonction range ().
def fizzbuzz(n):
n = int(n)
if (n%15) == 0: return "FizzBuzz"
elif (n%5) == 0: return "Buzz"
elif (n%3) == 0: return "Fizz"
else: return n
class FizzBuzzIterator:
def __init__(self,start, stop, step=1):
self.count = start
self.stop = stop
self.step = step
def __iter__(self):
return self
def next(self):
if (self.step > 0 and self.count >= self.stop) or (self.step < 0 and self.count <= self.stop):
raise StopIteration
else:
result = fizzbuzz(self.count)
self.count += self.step
return result
Sortie FizzBuzz de 1 à 100
fbiter1 = FizzBuzzIterator(1,101)
for fzbz in fbiter1: print fzbz
Sortie FizzBuzz uniquement pour les nombres impairs de 1 à 99
fbiter2 = FizzBuzzIterator(1,101,2)
for fzbz in fbiter2: print fzbz
Sortie FizzBuzz dans l'ordre inverse de 100 à 1
fbiter3 = FizzBuzzIterator(100,0,-1)
for fzbz in fbiter3: print fzbz
http://docs.python.jp/2/tutorial/classes.html#generator (Commencez à citer) Le générateur est un outil concis et puissant pour créer des itérateurs. Le générateur est écrit comme une fonction normale, mais lorsqu'il renvoie des données, il utilise une instruction yield. Chaque fois que next () est appelé, le générateur reprend le traitement précédemment interrompu (le générateur se souvient de toutes les valeurs de données et de la dernière instruction exécutée). Si vous regardez l'exemple ci-dessous, vous pouvez voir que le générateur est très facile à créer. (Fin de la citation)
Iterator semblait travailler très dur, mais le générateur devrait-il être simplement un document pour? Cela m'a fait me demander.
def fizzbuzz(n):
n = int(n)
if (n%15) == 0: return "FizzBuzz"
elif (n%5) == 0: return "Buzz"
elif (n%3) == 0: return "Fizz"
else: return n
def fizzbuzz_generator(start,finish,diff=1):
for n in range(start,finish,diff):
yield fizzbuzz(n)
for fzbz in fizzbuzz_generator(1,100):
print fzbz
http://docs.python.jp/2/glossary.html#term-decorator
(Commencez à citer)
(Décorateur) Une fonction qui renvoie une fonction. Il est généralement utilisé pour convertir une fonction avec la syntaxe «@ wrapper». Les utilisations courantes des décorateurs sont classmethod ()
et staticmethod ()
.
La grammaire du décorateur est le sucre de syntaxe. Les deux définitions de fonction suivantes sont sémantiquement identiques.
def f(...):
...
f = staticmethod(f)
@staticmethod
def f(...):
...
(Fin de la citation)
Je n'ai pas compris alors je l'ai écrit.
def fizzbuzz(n):
n = int(n)
if (n%15) == 0: return "FizzBuzz"
elif (n%5) == 0: return "Buzz"
elif (n%3) == 0: return "Fizz"
else: return n
def fizzbuzz_decorator(func):
def wrapper(*args, **kwargs):
func(fizzbuzz(*args))
return wrapper
@fizzbuzz_decorator
def f(n):
print n
f(1)
f(2)
f(3)
f(4)
f(5)
Dans ce qui précède, il semble que f soit réécrit par l'expression de décorateur @ fizzbuzz_decorator
, et f soit réécrit en fizzbuzz_decorator (f)
, c'est-à-dire la fonction wrapper () suivante.
def wrapper(*args, **kwargs):
f(fizzbuzz(args[0]))
Par conséquent, il semble que la chaîne de caractères fizzbuzz soit sortie car l'argument de f est traité par la fonction fizzbuzz () puis passé au f d'origine.
Résultat d'exécution
1
2
Fizz
3
Buzz
Il semble que les expressions de décorateur puissent également être imbriquées. http://docs.python.jp/2/reference/compound_stmts.html#function (Commencez à citer) Les définitions de fonction peuvent être enveloppées dans une ou plusieurs expressions de décorateur. Lorsque vous définissez une fonction, l'expression de décorateur est évaluée dans la portée qui contient la définition de fonction. Le résultat doit être un objet appelable qui prend un objet fonction comme seul argument. Au lieu d'un objet fonction, la valeur renvoyée est liée au nom de la fonction. Plusieurs décorateurs sont imbriqués et appliqués. (Fin de la citation)
def fizzbuzz(n):
n = int(n)
if (n%15) == 0: return "FizzBuzz"
elif (n%5) == 0: return "Buzz"
elif (n%3) == 0: return "Fizz"
else: return n
def fizzbuzz_decorator(func):
def wrapper(*args, **kwargs):
func(fizzbuzz(*args))
return wrapper
def fizzbuzz_decorator2(func):
def wrapper(*args, **kwargs):
for n in range(1,args[0]):
func(n)
return wrapper
@fizzbuzz_decorator2
@fizzbuzz_decorator
def f(n):
print n
f(101)
C'est un modèle équivalent au suivant.
f = fizzbuzz_decorator2(fizzbuzz_decorator(f))
Résultat d'exécution
1
2
Fizz
3
Buzz
(Omis)
98
Fizz
Buzz
Il semble que vous puissiez passer des arguments au décorateur, donc je l'ajouterai à l'avenir dès que j'enquêterai.
Recommended Posts