多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] > 生成器:generator > 通过列表⽣成式, 我们可以直接创建⼀个列表。 但是, 受到内存限制, 列表容量肯定是有限的。 ⽽且, 创建⼀个包含100万个元素的列表, 不仅占⽤很⼤的存储空间, 如果我们仅仅需要访问前⾯⼏个元素, 那后⾯绝⼤多数元素占⽤的空间都⽩⽩浪费了。 所以, 如果列表元素可以按照某种算法推算出来, 那我们是否可以在循环的过程中不断推算出后续的元素呢? 这样就不必创建完整的list, 从⽽节省⼤量的空间。简单来说,Python的生成器是一个返回可以迭代对象的函数。 ### 1. 生成器 ### 1.1 列表生成式的[]改成() ~~~ >>> x = range(0,9) >>> type(x) <class 'range'> >>> y = [i for i in x ] # 列表生成式 >>> type(y) <class 'list'> >>> y [0, 1, 2, 3, 4, 5, 6, 7, 8] >>> z = (i for i in x ) # 列表生成器 >>> type(z) <class 'generator'> >>> z >>> <generator object <genexpr> at 0x00000000021B9258> ~~~ ### 1.2 生成器函数 python 的生成器是一个可以重新启动的函数,你可以用yield来实现重新启动的功能.通过yield,这个函数就变成了一个生成器函数,它会返回一个迭带器,并可以将一个函数分成一系列的步骤来运行.迭带器的每一个循环都会重启这个函数,**这个函数会继续运行直到遇到下一个yield.** **.重启发生器的代码可以通过send 方法来获得这个值,将值发送给yield处的变量** > 1. 生成器函数包含一个或者多个yield > 2. 当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行 > 3. 像__iter__()和__next__()方法等是自动实现的,所以我们可以通过next()方法对对象进行迭代 > 4. 一旦函数被yield,函数会暂停,控制权返回调用者 > 5. 局部变量和它们的状态会被保存,直到下一次调用 > 6. 函数终止的时候,StopIteraion会被自动抛出 ~~~ import time # 简单的生成器函数 def my_gen(): n=1 print("first") # yield区域 yield n # 迭代一次,把值返回后,程序停在这里 print("停在这里了?1") n+=1 print("second") yield n # 迭代一次,返回值后程序停在这里 print("停在这里了?2") n+=1 print("third") yield n a=my_gen() print("next method:") # 每次调用a的时候,函数都从之前保存的状态执行 print(next(a)) time.sleep(1) print(next(a)) time.sleep(1) print(next(a)) time.sleep(1) print("for loop:") # 与调用next等价的 b=my_gen() for elem in my_gen(): print(elem) ~~~ ### 2. callable 英文文档: callable(object)   Return True if the object argument appears callable, False if not. If this returns true, it is still possible that a call fails, but if it is false, calling object will never succeed. Note that classes are callable (calling a class returns a new instance); instances are callable if their class has a __call__() method. **2. 可调用对象,在实际调用也可能调用失败;但是不可调用对象,调用肯定不成功。** #### 2.1 类对象 **类对象都是可被调用对象** ~~~ >>> class A: #定义类A pass >>> callable(A) #类A是可调用对象 True ~~~ #### 2.2 类的实例对象 **类的实例对象是否可调用对象,取决于类是否定义了__call__方法。** ~~~ >>> a = A() #调用类A >>> callable(a) #实例a不可调用 False >>> a() #调用实例a失败 Traceback (most recent call last): File "<pyshell#31>", line 1, in <module> a() TypeError: 'A' object is not callable >>> class B: #定义类B def __call__(self): print('instances are callable now.') >>> callable(B) #类B是可调用对象 True >>> b = B() #调用类B >>> callable(b) #实例b是可调用对象 True >>> b() #调用实例b成功 instances are callable now. ~~~ #### 2.3 函数 **函数必须是可调用的,要不然要函数干啥,其中当然包括匿名函数(lamda表达式)** ~~~ >>> tag_func = lambda x: x in tags >>> callable(tag_func) True ~~~