Cet article présente principalement une brève analyse de l'utilisation de Python rendement. L'éditeur pense que c'est assez bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur pour voir comment générer la séquence de Fibonacci
La séquence de Fibonacci est une séquenceRécursivetrès simple, sauf pour le premier et le deuxième nombres, n'importe quel nombre peut être obtenu en additionnant les deux premiers nombres. Utiliser un programme informatique pour générer les N premiers nombres de la séquence de Fibonacci est un problème très simple. De nombreux débutants peuvent facilement écrire la fonction suivante :
Listing 1. Sortie simple des N premiers nombres de la séquence de Fibonacci
def fab(max): n, a, b = 0, 0, 1 while n < max: print b a, b = b, a + b n = n + 1
En exécutant fab(5), nous pouvons obtenir la sortie suivante :
>> ;> ; fab(5)
1
1
2
3
5
Le résultat ne pose aucun problème, mais les développeurs expérimentés le feront remarquer directement en utilisant print imprimer des nombres dans la fonction fab rendra la fonction moins réutilisable, car la fonction fab renvoie None et les autres fonctions ne peuvent pas obtenir la séquence générée par la fonction.
Pour améliorer la réutilisabilité de la fonction fab, il est préférable de ne pas imprimer la séquence directement, mais de renvoyer une Liste. Ce qui suit est la deuxième version réécrite de la fonction fab :
Listing 2. Afficher les N premiers nombres de la séquence de Fibonacci Deuxième version
def fab(max): n, a, b = 0, 0, 1 L = [] while n < max: L.append(b) a, b = b, a + b n = n + 1 return L
Vous pouvez utiliser la méthode suivante pour imprimer la liste renvoyée par la fonction fab :
>>> for n in fab(5): ... print n ... 1 1 2 3 5
La fonction fab réécrite peut répondre aux exigences de réutilisabilité en renvoyant une liste, mais les développeurs plus expérimentés le feront. a souligné que la mémoire occupée par cette fonction pendant le fonctionnement augmentera à mesure que le paramètre max augmentera. Si vous souhaitez contrôler l'occupation de la mémoire, il est préférable de ne pas utiliser List pour enregistrer les résultats intermédiaires, mais d'utiliser un objet < itérable. 🎜> Itérer. Par exemple, en Python2 http://www.php.cn/wiki/1078.html" target="_blank">range(1000): pass entraînera l'affichage d'une liste de 1000 éléments. généré, et le code :
ne générera pas une liste de 1000 éléments, mais renverra la valeur suivante à chaque itération, occupant très peu d'espace mémoire. Parce que xrange ne renvoie pas une liste, mais un objet itérable.
En utilisant iterable, nous pouvons réécrire la fonction fab dans uneclass for i in <a href="http://www.php.cn/wiki/1078.html" target="_blank">range</a>(1000): pass
qui prend en charge iterable :
for i in xrange(1000): pass
<🎜. >Listing 4. La troisième version
Cependant, le code de cette version réécrite en utilisant class est bien moins concis que la première version de la fonction fab. Yield est pratique si nous voulons conserver la simplicité de la première version de la fonction fab tout en obtenant des effets itérables :
class Fab(object): def init(self, max): self.max = max self.n, self.a, self.b = 0, 0, 1 def iter(self): return self def next(self): if self.n < self.max: r = self.b self.a, self.b = self.b, self.a + self.b self.n = self.n + 1 return r raise StopIteration()
>>> for n in Fab(5): ... print n ... 1 1 2 3 5
Pour faire simple, la fonction de rendement est de tourner une fonction dans un générateur, la fonction avec rendement n'est plus une fonction ordinaire. L'interpréteur Python la traitera comme un générateur. L'appel de fab(5) n'exécutera pas la fonction fab, mais renverra un objet itérable ! Lorsque la boucle for
def fab(max): n, a, b = 0, 0, 1 while n < max: yield b # print b a, b = b, a + b n = n + 1 '''
est exécutée, chaque boucle exécutera le code à l'intérieur de la fonction fab. Lorsqu'elle atteint le rendement b, la fonction fab renvoie une valeur d'itération. Dans l'itération suivante, le code commence à partir de l'instruction suivante. de rendement b. L'exécution continue et la
variable locale
>>> for n in fab(5): ... print n ... 1 1 2 3 5
Listing 6. Processus d'exécution
一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。 yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。 如何判断一个函数是否是一个特殊的 generator 函数?可以利用 isgeneratorfunction 判断: 清单 7. 使用 isgeneratorfunction 判断 要注意区分 fab 和 fab(5),fab 是一个 generator function,而 fab(5) 是调用 fab 返回的一个 generator,好比类的定义和类的实例的区别: 清单 8. 类的定义和类的实例 每次调用 fab 函数都会生成一个新的 generator 实例,各实例互不影响: return 的作用 在一个 generator function 中,如果没有 return,则默认执行至函数完毕,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。 另一个例子 另一个 yield 的例子来源于文件读取。如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容。通过 yield,我们不再需要编写读文件的迭代类,就可以轻松实现文件读取: 清单 9. 另一个 yield 的例子 Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois! >>> from inspect import isgeneratorfunction
>>> isgeneratorfunction(fab)
True
>>> import types
>>> isinstance(fab, types.GeneratorType)
False
>>> isinstance(fab(5), types.GeneratorType)
True
fab 是无法迭代的,而 fab(5) 是可迭代的:
>>> from collections import Iterable
>>> isinstance(fab, Iterable)
False
>>> isinstance(fab(5), Iterable)
True
>>> f1 = fab(3)
>>> f2 = fab(5)
>>> print 'f1:', f1.next()
f1: 1
>>> print 'f2:', f2.next()
f2: 1
>>> print 'f1:', f1.next()
f1: 1
>>> print 'f2:', f2.next()
f2: 1
>>> print 'f1:', f1.next()
f1: 2
>>> print 'f2:', f2.next()
f2: 2
>>> print 'f2:', f2.next()
f2: 3
>>> print 'f2:', f2.next()
f2: 5
def read_file(fpath):
BLOCK_SIZE = 1024
with open(fpath, 'rb') as f:
while True:
block = f.read(BLOCK_SIZE)
if block:
yield block
else:
return