Maison > développement back-end > Tutoriel Python > Explication détaillée des générateurs, itérateurs, attributs et méthodes ajoutés dynamiquement en Python

Explication détaillée des générateurs, itérateurs, attributs et méthodes ajoutés dynamiquement en Python

WBOY
Libérer: 2023-04-21 13:22:08
avant
1379 Les gens l'ont consulté

1. Générateur

1. Définition du générateur

En Python, le mécanisme qui calcule en boucle s'appelle un générateur : générateur

2 La signification du générateur

Toutes les données de la liste sont en mémoire. grande quantité de données, cela consommera beaucoup de mémoire.

Par exemple : si vous n'avez besoin d'accéder qu'aux premiers éléments, alors tout l'espace suivant sera gaspillé

Si les éléments de la liste sont calculés selon un certain algorithme, vous pouvez calculer en continu les éléments suivants pendant la boucle, donc vous n'avez pas besoin de créer une liste complète, ce qui permet d'économiser beaucoup d'espace.

3. Méthode 1 de création d'un générateur (expression du générateur)

L'expression du générateur est très simple. Il suffit de changer [] dans une compréhension de liste en () pour créer un générateur (générateur) :

L = [x * x for x in range(10)]  #推导式
print(L)
g = (x * x for x in range(10)) #加成括号就是生成器
print(g)
#<generator object <genexpr> at 0x1022ef630>
&#39;&#39;&#39;L是一个list,而g则是一个 generator&#39;&#39;&#39;
Copier après la connexion

4. créer un générateur (fonction générateur)

1. Fonction générateur
  • Si une fonction contient le mot-clé rendement, alors la fonction n'est plus une fonction ordinaire, c'est créer un objet générateur

  • Fonction générateur : Utilisez le mot-clé rendement pour renvoyer un résultat à la fois, bloquer et recommencer

2. Comment fonctionne la fonction génératrice
  • La fonction génératrice renvoie un itérateur, la boucle for appelle en permanence la fonction __next__() sur celui-ci. itérateur, et continue de courir jusqu'à l'instruction de rendement suivante, obtenant chaque valeur de retour une à la fois, jusqu'à ce qu'il n'y ait plus d'instruction de rendement, et déclenche finalement une exception StopIteration

  • le rendement est tout à fait renvoyé une valeur au retour et rappelez-vous le position renvoyée. Lors de la prochaine itération, le code commencera à s'exécuter à partir de l'instruction suivante (pas de la ligne suivante) de rendement

  • send(), comme next(), peut générer Le générateur descend d'un cran (s'arrête la prochaine fois). il rencontre le rendement), mais send() peut transmettre une valeur, qui est utilisée comme résultat global de l'expression de rendement

Principe de fonctionnement du générateur de test (yield)

&#39;&#39;&#39;
如果一个函数中包含 yield 关键字,那么这个函数就不再是一个普通函数,
调用函数就是创建了一个生成器(generator)对象
生成器函数:其实就是利用关键字 yield 一次性返回一个结果,阻塞,重新开始
原理
1. 函数有了yield之后,调用它,就会生成一个生成器
2. 下次从下一个语句执行,切记不是下一行(tmp = yield i)
3. return在生成器中代表生成器种植,直接报错:StopIeratation
4. next方法作用:唤醒并继续执行
&#39;&#39;&#39;
def test():
    print("start")
    i = 0
    while i<3:
        &#39;&#39;&#39;yield i #第一次执行,此处挂起;同时将i的值返回到i
                   #第二次执行,从挂起的地方往下执行&#39;&#39;&#39;
        temp = yield i #下次迭代时,代码从`yield`的下一条语句(不是下一行)开始执行
        print(f"i:{i}")
        i += 1
    print("end")
    return "done"
if __name__ == &#39;__main__&#39;:
    a = test()
    print(type(a))
    print(a.__next__())
    print(a.__next__())
    print(a.__next__())
    print(a.__next__())# 抛出异常:StopIteration
&#39;&#39;&#39;
<class &#39;generator&#39;>
start
0
temp:None
1
temp:None
2
temp:None
end
Traceback (most recent call last):
 in <module>
    print(a.__next__())# 抛出异常:StopIteration
StopIteration: done
&#39;&#39;&#39;
Copier après la connexion

Principe de fonctionnement du générateur de test (envoyer)

&#39;&#39;&#39;
send的作用是唤醒并继续执行,发送一个信息到生成器内部
&#39;&#39;&#39;
def foo():
    print("start")
    i = 0
    while i < 2:
        temp = yield i
        print(f"temp:{temp}")
        i += 1
    print("end")
 
g = foo()
print(next(g))  #等同g.__next__(),next是内置函数
print("*"*20)
print(g.send(100))
print(next(g))
# for a in g:#g所返回的值是yield处的i
#     print(a)
&#39;&#39;&#39;
start
0
********************
temp:100
1
temp:None
end
Traceback (most recent call last):
    print(next(g))
StopIteration
&#39;&#39;&#39;
Copier après la connexion

5. Résumé

1. Qu'est-ce qu'un générateur

Le générateur enregistre uniquement un ensemble d'algorithmes pour générer des valeurs et ne permet pas à l'algorithme de commencer à s'exécuter maintenant, mais lorsque vous l'appelez, quand commence-t-il à calculer une nouvelle valeur et vous la renvoie

2. Fonctionnalités du générateur
  • La fonction générateur génère une série de résultats. Après avoir renvoyé une valeur via le mot-clé rendement, il peut continuer à s'exécuter à partir de l'endroit où il est sorti, de sorte qu'une série de valeurs peut être générée à tout moment.

  • Les générateurs et les itérations sont étroitement liés. Les itérateurs ont une méthode membre __next__(), qui renvoie l'élément suivant de l'itération ou provoque une exception pour mettre fin à l'itération.

  • Un générateur est un programme spécial qui peut être utilisé pour contrôler le comportement itératif d'une boucle,

2. Itérateur

1 Concept

  • L'itération est l'une des fonctionnalités les plus puissantes de Python, C'est un moyen d'accéder aux éléments d'une collection

  • Un itérateur est un objet qui peut se souvenir de la position parcourue

  • L'objet itérateur commence à accéder à partir du premier élément de l'ensemble jusqu'à ce que tous les éléments aient été accédés

  • Les itérateurs ne peuvent qu'avancer et non reculer

  • Les itérateurs ont deux méthodes de base : iter() et netx()

2 La différence entre les objets itérables et les itérateurs

  • Un objet. qui implémente la méthode iter est appelé "Objet itérable Ieratable"

  • Un objet qui implémente la méthode suivante et qui est itérable est appelé un "itérateur". Itérateur signifie : implémente la méthode iter et next L'objet de la méthode est l'itérateur

! Les générateurs sont tous des objets Iterator, mais list , dict , str Bien qu'ils soient tous Itérables (objets itérables), ce ne sont pas des itérateurs

&#39;&#39;&#39;
生成器一定是迭代器
可迭代对象不一定是迭代器,使用iter([])封装后可转为迭代器
&#39;&#39;&#39;
from collections.abc import Iterator
from collections.abc import Iterable
a = isinstance([], Iterator) #list、dict、str虽然是Iterable(可迭代对象),却不是Iterator(迭代器)
print(a)
a = isinstance([], Iterable) #可迭代对象
print(a)
"""
执行结果:
False
True
"""
Copier après la connexion
&#39;&#39;&#39;list、dict、str 等 Iterable 变成 Iterator,可以使用 iter() 函数:&#39;&#39;&#39;
b = isinstance(iter([]), Iterator)
print(b)
b = isinstance(iter(&#39;花非人陌&#39;), Iterator)
print(b)
 
"""
执行结果:
True
True
"""
Copier après la connexion

Explication détaillée des générateurs, itérateurs, attributs et méthodes ajoutés dynamiquement en Python

Python Le Itérateur L'objet représente un flux de données . Ces données peuvent être considérées comme une séquence ordonnée, mais nous ne pouvons pas connaître la longueur de la séquence à l'avance. Nous ne pouvons calculer en continu les données suivantes à la demande que via la fonction next() , donc le calcul de Iterator est paresseux. . Il n'est calculé que lorsque les données suivantes doivent être renvoyées.

Donc, le générateur doit être un itérateur.

3. L'essence de la boucle for

#Python3 的 for 循环本质就是通过不断调用 next() 函数实现的。
 
for x in [1,2,3,4,5]:
    pass
 
&#39;&#39;&#39;本质是:&#39;&#39;&#39;
#首先获得Iterator对象:
it = iter([1,2,3,4,5])
#循环
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration 就退出循环
        break
Copier après la connexion

4. Créer un itérateur

Utiliser une classe comme itérateur nécessite d'implémenter deux méthodes dans la classe __iter__() et __next__()

  • Le La méthode __iter__() renvoie un objet itérateur spécial qui implémente la méthode __next__() et identifie la fin de l'itération via l'exception StopIteration

  • __next__() 方法会返回下一个迭代器对象

#创建一个依次返回10,20,30,...这样数字的迭代器
class MyNumbers:
    def __iter__(self):
        self.num = 10
        return self
 
    def __next__(self):
        if self.num < 40:
            x = self.num
            self.num += 10
            return x
        else:
            raise StopIteration
 
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
"""
执行结果:
10
20
30
Traceback (most recent call last):
    raise StopIteration
StopIteration
"""
"""
程序解析:
在这段代码中,MyNumbers 类定义了一个迭代器。该迭代器的作用是生成一系列数字,从 10 开始,每次增加 10,直到 40,然后停止。
在程序中,通过 iter(myclass) 方法获取 MyNumbers 类的迭代器对象 myiter,然后调用 next(myiter) 方法获取下一个数字。
在第一次调用 next(myiter) 方法时,迭代器会执行 __next__() 方法,返回 self.num 的值 10,然后将 self.num 的值增加 10,变为 20。
在第二次、第三次调用 next(myiter) 方法时,迭代器会再次执行 __next__() 方法,返回 20 和 30,然后将 self.num 的值分别增加 10,变为 30 和 40。
在第四次调用 next(myiter) 方法时,迭代器再次执行 __next__() 方法,发现 self.num 的值已经大于等于 40,于是抛出 StopIteration 异常,表示迭代已经结束。
"""
Copier après la connexion

三、动态添加属性和方法

1、动态编程语言定义

指在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,

已有的函数可以被删除或是其他结构上的变化

2、运行过程中给对象添加属性和方法

#coding=utf-8
import types
class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
p1 = Person("zhangsan", 20)
p2 = Person("lisi", 18)
#动态给对象添加属性和方法
p1.score = 100
print(p1.score) #加给p1的只能p1用,对象的也是一样
 
#动态给对象添加方法
def run(self):
    print(f"{self.name}, running...")
p1.run = types.MethodType(run, p1)
#而types.MethodType(run,p1)则是告诉解释器,self指的就是p1
p1.run()
"""
执行结果:
100
zhangsan, running...
"""
Copier après la connexion

3、给类动态添加静态方法以及类方法

#encoding=utf-8
class Person():
    __slots__ = {"name", "age"}
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
@staticmethod
def staticfunc():
    print("--- static method ---")
 
Person.staticfunc = staticfunc
Person.staticfunc()
Person.score = 1000 #动态给对象静态方法
print(Person.score)
 
@classmethod
def clsfunc(cls):
    print(&#39;--- cls method ---&#39;)
Person.clsfunc = clsfunc    #动态增加类方法
Person.clsfunc()
Copier après la connexion

四、限制动态添加

1、slots

1. __slots__的作用
  • __slots__ 对动态添加成员变量、成员方法有限制。对动态添加类属性、类方法没有限制

  • __slots__ 只对本类有限制,不限制子类

2. 对动态添加成员变量、成员方法有限制
&#39;&#39;&#39;
MyClass 类使用 __slots__ 属性限制了实例对象的属性,只允许动态添加 x 属性。
因此,obj.x = 1 可以成功,但是 obj.y = 2 会抛出 AttributeError 异常
&#39;&#39;&#39;
class MyClass:
    __slots__ = [&#39;x&#39;]
 
obj = MyClass()
obj.x = 1  # 可以动态添加 x 属性
obj.y = 2  # 报错,__slots__ 限制了不能动态添加 y 属性
"""
执行结果:
AttributeError: &#39;MyClass&#39; object has no attribute &#39;y&#39;
"""
Copier après la connexion
3. 对动态添加类属性、类方法没有限制
class MyClass:
    __slots__ = [&#39;x&#39;]
    classattr = 1
 
    @classmethod
    def myclassmethod(cls):
        print("class method")
 
 
MyClass.newclassattr = 2  # 可以动态添加类属性
print(MyClass.newclassattr)
MyClass.mynewclassmethod = lambda cls: print("new class method")  # 可以动态添加类方法
MyClass.mynewclassmethod(MyClass)   #传递类本身作为参数
obj = MyClass()
obj.x  = 3    # 可以动态添加实例属性
print(obj.x)  # 可以动态添加 x 属性
"""
执行结果:
2
new class method
3
"""
Copier après la connexion

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!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal