生成器简述 - python 基础进阶知识点补全(一)
可迭代对象:
可以用于for ... in ..循环对对象都是可迭代对象,比如: list tuple dict set
可以迭代的对象就是可迭代对象,python 中一切都是对象,在这里主要说的是变量
a = [1,2,3] b = (1,2,3,) c = "1234"
对象就是 a、 b 、 c 因为a、 b、 c 可以被迭代(可以通过for 循环获取其中每一个单位元素) 所以被称为可迭代对象。
可迭代对象需满足: 实现了魔法方法,__iter__方法
魔法方法: 是python内置方法,不需要主动调用,存在的目的是为了给python解释器调用
魔术方法在类或对象的某些事件出发后会自动执行,如果希望根据自己的程序定制特殊功能的类,那么就需要对这些方法进行重写。使用这些「魔法方法」,我们可以非常方便地给类添加特殊的功能。
自动执行:
报错提示:
在代码最后:
b = Box(10, 20, 30) # 在这我并没有对它(__init__方法 )做调用 print(b.getVolume())
虽然我对 __init__ 方法没做调用 显然它是执行了,如何证明它是执行的, 我把实例化的
height 和 depath 属性给注释了,所以在我调用了 b.getVolume() 方法后他给我提示错误。
__iter__方法:
迭代器:
迭代器即用来迭代取值的工具,是一个可以记住遍历的位置的对象。 # 重要
迭代器对象从集合的第一个元素开始访问,直到抛出 StopIteration 异常 即是所有元素被访问完成。
迭代器特点:
- 迭代器是一个可以记住遍历的位置的对象。
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退
如果一个对象定义了下面两种方法,即是迭代器
__iter__(self)
__next__(self)next()方法的作用是获取容器的下一个值,但如果调用了next方法,容器没有值可以返回,则会抛出一个StopIteration异常。
这就是为什么能记得住 遍历的位置
生成器:
生成器的语法规则:
(exp for iter_var in iterable if_exp)
从形式上看生成器和列表生成式非常相似,从形式上看生成器和列表生成式非常相似,生成器仅仅是将列表生成式的方括号换成了圆括号。而实际使用上却有很大的差别,列表生成式一次生成一个列表若列表的元素过多则占用很大的内存空间,而生成器一次仅生成一个元素即节省了内存空间又可以获取完整的列表内容。
列表生成式:
excep = [exp for iter_list in iterable if element_list ]
列表生成式,关键性的作用没有只是简化整理了步骤,
就拿下面这个代码来看我用传统的写法写一遍
# 普通写法
a = [1,2,3,4,5,6]
list_excep = [ ]
for exp in a :
if exp > 2:
b = exp * exp
list_excep.append(b)
print(list_excep )
# 列表生成式
a = [1,2,3,4,5,6]
list_excep = [exp * exp for exp in a if exp > 2]
print(list_exp)
列表生成式一次生成一个列表若列表的元素过多则占用很大的内存空间,而生成器一次仅生成一个元素即节省了内存空间又可以获取完整的列表内容。
图 3 -1
注意:图 3 - 1 这个返回对象
<generator object <genexpr> at 0x000001D7A0302180>
直译为“生成器对象genexp在0x000001D7A0302180”,也就是说函数返回的不是列表,而是一个“生成器对象”。什么是生成器对象呢 ?
原来生成器对象是一个可以产生数据,我们可以对起进行迭代或称为遍历
生成器是一种迭代器,生成器拥有next方法并且行为和迭代器相同,都可以用于for循环。
生成器对延迟操作提供了支持,这使得python可以在需要的时候才生成结果,而不是立即产生结果。生成器更加高效的利用内存, 当需要产生大量数据时, 使用生成器返回一个惰性的迭代器, 而不是在内存中保存他们。
python 实现了 __next__ 方法的对象都可以称为迭代器
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
生成器是在迭代器的基础之上的,生成器简单理解就是一个迭代器,因为上文以及图3- 1 中证明了它返回的是一个可迭代的对象。
yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。
当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并保存当前迭代的位置,并将 yield 后面的表达式作为当前迭代的值返回
a = [1,2,3,4]
for i in a :
# 第一迭代获取元素下标为 0 值 为 1
# 第二次迭代获取元素下标为1 值为 2
现在遇到了yield 停在下标为 1 的位置 ,它会记住,奥我现在到了 列表对象 [1,2,3,4] 中下标为 1 的位置,并且我将 元素 2 作为当前迭代的值返回,并在保证在下一次执行 next() 方法时,从yield 记忆的位置也就时下标为1 的地方开,等到再次遇见 yield 时,我在记忆,在返回。
文章部分材料来源:
http://t.csdnimg.cn/c7nyU
谢谢各位同僚对本文章的支持,能力有限我会努力提升自己争取为大家提供更多有用的知识
学了这么久的程序,我觉得最大的感受,提升这个阶段, 往往意味着 在搜寻自己所需要的知识类,整理自己的知识面,我不知道这是不是学习能力,但是有几点我自己写代码的能力的确提高了对知识尤其是广度比较好,记得大一的时候,我还需要看着书一个一个写,目前看几眼就记住了,以前呢? 还有看缩进标点符号是否加错, 现在很少写错,即便不对一找就准,对知识的把握也就是,你知道需要什么,应该怎么去找,而且保证找到的内容是有效的,但是目前缺乏的能力是归纳整理,我为此尝试了 x -mind 思维脑图 ,并且我认为它是正确的 ,它的作用是用来加强知识面的理解记忆,但是确实很难,你在写的写的就忘记了写了, 这是人惰性包括 ,思维 跳跃提升需要改变,大脑它在抵抗,所以很麻烦。
图为 - xmind 使用