Maison > Article > développement back-end > Introduction à l'utilisation du mot-clé rendement en python (exemple de code)
Cet article vous apporte une introduction à l'utilisation du mot-clé rendement en Python (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.
yield est un mot-clé en python. Lorsque je suis entré en contact avec python pour la première fois, je ne comprenais pas ce mot-clé. Ce n'est qu'après l'avoir maîtrisé que j'ai réalisé que cet article était très utile. va déterminer comment utiliser le rendement .
1 Utilisez rendement pour créer un générateur
En python, un générateur est un objet itérable, mais un objet itérable n'est pas nécessairement un générateur.
Par exemple, la liste est un objet itérable
>>> a = list(range(3)) >>> for i in a: print(i) 0 1 2 3
Mais toutes les valeurs d'un objet liste sont stockées en mémoire Si la quantité de données est très importante, la mémoire peut ne pas être suffisante. ; this Dans ce cas, vous pouvez générer un générateur. Par exemple, Python peut utiliser "()" pour construire un objet générateur :
>>> b = (x for x in range(3)) >>> for i in b: print(i) 0 1 2 >>> for i in b: print(i) >>>
Le générateur peut être itéré et les données sont générées en réel. temps, et ne seront pas tous enregistrés en mémoire. Il est à noter que le générateur ne peut être lu qu'une seule fois. Comme vous pouvez le voir à partir des résultats d'exécution ci-dessus, le résultat de sortie de la deuxième boucle for est vide. >.
Dans la programmation réelle, si une fonction doit générer une donnée sérialisée, le moyen le plus simple est de mettre tous les résultats dans une liste et de la renvoyer. Si la quantité de données est importante, vous devriez envisager de l'utiliser. un générateur Pour réécrire une fonction qui renvoie directement une liste (Effective Python, Item 16>>> def get_generator(): for i in range(3): print('gen ', i) yield i >>> c = get_generator() >>> c = get_generator() >>> for i in c: print(i) gen 0 0 gen 1 1 gen 2 2Comme le montre le code ci-dessus, lorsque la fonction get_generator est appelée, le code à l'intérieur de la fonction le fera). ne sera pas exécuté, mais renverra Un objet itérateur est obtenu et le code de la fonction ne sera exécuté que lors d'une itération avec une boucle for.
En plus d'utiliser une boucle for pour obtenir la valeur renvoyée par le générateur, vous pouvez également utiliser next et send
>>> c = get_generator() >>> print(next(c)) gen 0 0 >>> print(next(c)) gen 1 1 >>> print(next(c)) gen 2 2 >>> print(next(c)) Traceback (most recent call last): File "<pyshell#59>", line 1, in <module> print(next(c)) StopIteration
>>> c = get_generator() >>> c.send(None) gen 0 0 >>> c.send(None) gen 1 1 >>> c.send(None) gen 2 2 >>> c.send(None) Traceback (most recent call last): File "<pyshell#66>", line 1, in <module> c.send(None) StopIteration
Une fois le résultat du générateur lu, une exception StopIteration sera générée.
2 Utilisation de
yield dans les coroutines Un scénario d'utilisation courant consiste à implémenter des coroutines via le rendement. modèle à titre d'exemple :# import logging # import contextlib # def foobar(): # logging.debug('Some debug data') # logging.error('Some error data') # logging.debug('More debug data') # @contextlib.contextmanager # def debug_logging(level): # logger = logging.getLogger() # old_level = logger.getEffectiveLevel() # logger.setLevel(level) # try: # yield # finally: # logger.setLevel(old_level) # with debug_logging(logging.DEBUG): # print('inside context') # foobar() # print('outside context') # foobar() def consumer(): r = 'yield' while True: print('[CONSUMER] r is %s...' % r) #当下边语句执行时,先执行yield r,然后consumer暂停,此时赋值运算还未进行 #等到producer调用send()时,send()的参数作为yield r表达式的值赋给等号左边 n = yield r #yield表达式可以接收send()发出的参数 if not n: return # 这里会raise一个StopIteration print('[CONSUMER] Consuming %s...' % n) r = '200 OK' def produce(c): c.send(None) n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r = c.send(n) #调用consumer生成器 print('[PRODUCER] Consumer return: %s' % r) c.send(None) c.close() c = consumer() produce(c)
[CONSUMER] r is yield... [PRODUCER] Producing 1... [CONSUMER] Consuming 1... [CONSUMER] r is 200 OK... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 2... [CONSUMER] Consuming 2... [CONSUMER] r is 200 OK... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 3... [CONSUMER] Consuming 3... [CONSUMER] r is 200 OK... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 4... [CONSUMER] Consuming 4... [CONSUMER] r is 200 OK... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 5... [CONSUMER] Consuming 5... [CONSUMER] r is 200 OK... [PRODUCER] Consumer return: 200 OK Traceback (most recent call last): File ".\foobar.py", line 51, in <module> produce(c) File ".\foobar.py", line 47, in produce c.send(None) StopIterationComme vous pouvez le voir dans l'exemple ci-dessus, l'expression de rendement coopère avec l'envoi de données d'échange
n = yield r r = c.send(n)
3 contextmanager. Un autre scénario d'utilisation intéressant de
est dans contextmanager, comme suit :import logging import contextlib def foobar(): logging.debug('Some debug data') logging.error('Some error data') logging.debug('More debug data') @contextlib.contextmanager def debug_logging(level): logger = logging.getLogger() old_level = logger.getEffectiveLevel() logger.setLevel(level) try: yield #这里表示with块中的语句 finally: logger.setLevel(old_level) with debug_logging(logging.DEBUG): print('inside context') foobar() print('outside context') foobar()
inside context DEBUG:root:Some debug data ERROR:root:Some error data DEBUG:root:More debug data outside context ERROR:root:Some error dataDans le code ci-dessus, en utilisant le gestionnaire de contexte (contextmanager ), le niveau du journal est amélioré lorsque l'expression de rendement arrive. Yield représente l'instruction dans le bloc with
Résumé
L'expression de rendement peut créer un générateur, et vous devriez le faire. pensez à utiliser un générateur pour réécrire la fonction qui renvoie directement la liste Étant donné que le générateur ne peut être lu qu'une seule fois, une attention particulière doit être portée lors de l'utilisation d'une boucle for pour parcourir si le générateur continue de lire après la lecture ; , une exception StopIteration sera levée. En fait, cette exception peut être utilisée en programmation comme base pour juger de la fin de la lecture Un scénario d'utilisation courant de rendement consiste à implémenter des coroutines en coopérant avec l'envoi ; fonction, il peut obtenir l'effet d'échange de données ;yield peut également représenter l'instruction dans le bloc with dans la fonction décorée par contextmanager
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!