In Python, the mechanism that calculates while looping is called a generator: generator
All data in the list are in memory. If there is a large amount of data, it will consume a lot of memory.
For example: if you only need to access the first few elements, then all the subsequent space will be wasted
If the list elements are calculated according to a certain algorithm, you can continuously calculate the subsequent elements during the loop. elements, so you don't have to create a complete list, thus saving a lot of space.
The generator expression is very simple. Just change [] of a list comprehension to () to create a Generator:
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> '''L是一个list,而g则是一个 generator'''
If a If the function contains the yield keyword, then this function is no longer an ordinary function. Calling the function creates a generator object
Generator function: using the key The word yield returns a result at once, blocks, and starts again
The generator function returns an iteration The for loop continuously calls the __next__() function on this iterator, and continues to run to the next yield statement, obtaining each return value one at a time, until there is no yield statement, and finally triggers the StopIteration exception
yield is equivalent to return, which returns a value and remembers the returned position. During the next iteration, the code starts executing from the next statement (not the next line) of yield
send(), like next(), can make the generator go one step further (stop when it encounters yield next time), but send() can pass a value, which is used as the overall result of the yield expression
How the test generator works (yield)
''' 如果一个函数中包含 yield 关键字,那么这个函数就不再是一个普通函数, 调用函数就是创建了一个生成器(generator)对象 生成器函数:其实就是利用关键字 yield 一次性返回一个结果,阻塞,重新开始 原理 1. 函数有了yield之后,调用它,就会生成一个生成器 2. 下次从下一个语句执行,切记不是下一行(tmp = yield i) 3. return在生成器中代表生成器种植,直接报错:StopIeratation 4. next方法作用:唤醒并继续执行 ''' def test(): print("start") i = 0 while i<3: '''yield i #第一次执行,此处挂起;同时将i的值返回到i #第二次执行,从挂起的地方往下执行''' temp = yield i #下次迭代时,代码从`yield`的下一条语句(不是下一行)开始执行 print(f"i:{i}") i += 1 print("end") return "done" if __name__ == '__main__': a = test() print(type(a)) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__())# 抛出异常:StopIteration ''' <class 'generator'> start 0 temp:None 1 temp:None 2 temp:None end Traceback (most recent call last): in <module> print(a.__next__())# 抛出异常:StopIteration StopIteration: done '''
How the test generator works (send)
''' send的作用是唤醒并继续执行,发送一个信息到生成器内部 ''' 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) ''' start 0 ******************** temp:100 1 temp:None end Traceback (most recent call last): print(next(g)) StopIteration '''
The generator only saves a set of algorithms for generating values, and does not let the algorithm start executing now, but when I call it , when it starts to calculate a new value and returns you
The generator function generates a series of results. After returning a value through the yield keyword, it can continue running from where it exited, so a series of values can be generated at any time.
Generators and iterations are closely related. Iterators have a __next__() member method, which either returns the next item of the iteration or causes an exception to end the iteration.
A generator is a special program that can be used to control the iterative behavior of a loop.
Iteration is one of the most powerful functions of Python and is a way to access collection elements
Iterator It is an object that can remember the traversed position
The iterator object starts accessing from the first element of the collection until all elements have been accessed
Iterators can only go forward and not backwards
Iterators have two basic methods: iter()andnetx( )
An object that implements the iter method is called an "iterable" Object Ieratable"
An object that implements the next method and is iterable is called an "iterator" Iterator. That is, an object that implements the iter method and next method is an iterator
! Generators are all Iterator objects, but list , dict , str are all Iterable (Iterable object), but not Iterator (Iterator)
''' 生成器一定是迭代器 可迭代对象不一定是迭代器,使用iter([])封装后可转为迭代器 ''' 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 """
'''list、dict、str 等 Iterable 变成 Iterator,可以使用 iter() 函数:''' b = isinstance(iter([]), Iterator) print(b) b = isinstance(iter('花非人陌'), Iterator) print(b) """ 执行结果: True True """
3. The essence of for loopPython's Iterator The object represents adata flow. This data can be regarded as an ordered sequence, but we cannot know the length of the sequence in advance. We can only calculate the next data on demand through the next() function, so Iterator # The calculation of ## is lazy, it will only be calculated when the next data needs to be returned.
So, the generator must be an iterator.
#Python3 的 for 循环本质就是通过不断调用 next() 函数实现的。 for x in [1,2,3,4,5]: pass '''本质是:''' #首先获得Iterator对象: it = iter([1,2,3,4,5]) #循环 while True: try: # 获得下一个值: x = next(it) except StopIteration: # 遇到StopIteration 就退出循环 break
__iter__() and __next__()
The method returns a special iterator object. This iterator The object implements the __next__() method and identifies the completion of iteration through the StopIteration exception
__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 异常,表示迭代已经结束。 """
指在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,
已有的函数可以被删除或是其他结构上的变化
#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... """
#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('--- cls method ---') Person.clsfunc = clsfunc #动态增加类方法 Person.clsfunc()
__slots__ 对动态添加成员变量、成员方法有限制。对动态添加类属性、类方法没有限制
__slots__ 只对本类有限制,不限制子类
''' MyClass 类使用 __slots__ 属性限制了实例对象的属性,只允许动态添加 x 属性。 因此,obj.x = 1 可以成功,但是 obj.y = 2 会抛出 AttributeError 异常 ''' class MyClass: __slots__ = ['x'] obj = MyClass() obj.x = 1 # 可以动态添加 x 属性 obj.y = 2 # 报错,__slots__ 限制了不能动态添加 y 属性 """ 执行结果: AttributeError: 'MyClass' object has no attribute 'y' """
class MyClass: __slots__ = ['x'] 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 """
The above is the detailed content of Detailed explanation of generators, iterators, dynamically added attributes and methods in Python. For more information, please follow other related articles on the PHP Chinese website!