便利的响应式网站建设qq群推广网站
人生苦短,我用python
python 安装包+资料:点击此处跳转文末名片获取
1.实现generator的两种方式
python中的generator保存的是算法,
真正需要计算出值的时候才会去往下计算出值。
它是一种惰性计算(lazy evaluation)。
要创建一个generator有两种方式。
第一种方法:
把一个列表生成式的[]改成(),
就创建了一个generator:
>>> L=[x * x for x in range(10)]
>>> L
[0,1,4,9,16,25,36,49,64,81]
>>> g = (x * x for x in range(10))#注意把[]改成()后,不是生成一个tuple,而是生成一个generator
>>> g
<generator object <genexpr> at 0x1022ef630>
第二种方式:
在函数中使用yield关键字,函数就变成了一个generator。
函数里有了yield后,执行到yield就会停住,
当需要再往下算时才会再往下算。
所以生成器函数即使是有无限循环也没关系,
它需要算到多少就会算多少,不需要就不往下算。
def fib():a,b = 0,1while True:yield aa, b = b, a + bf = fib()
print (f, next(f),next(f),next(f))
#<generator object fib at 0x7f89769d1fa0> 0 1 1
如上例,第一次输出f,
它就是一个generator,
之后每次next,它就执行到yield a。
当然其实平常很少用到next(),
我们直接用for循环就可以遍历一个generator,
其实for循环的内部实现就是不停调用next()。
生成器可以避免不必要的计算,
带来性能上的提升;
而且会节约空间,
可以实现无限循环(无穷大的)的数据结构。
2.可迭代对象(Iterable)和迭代器(Iterator)的概念
可以直接作用于for循环的对象统称为可迭代对象:Iterable
。
包括集合数据类型(list、tuple、dict、set、str等)
和生成器(generator)。
可以使用isinstance()
判断一个对象是否是Iterable对象。
>>>from collections import Iterable
>>> isinstance([],Iterable)
True
>>> isinstance({},Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)),Iterable)
True
>>> isinstance(100,Iterable)
False
迭代器:Iterator。
它表示的是一个数据流,
Iterator对象可以被next()函数调用并不断返回下一个数据,
直到没有数据时抛出StopIteration错误。
可以把这个数据流看做是一个有序序列,
但我们却不能提前知道序列的长度,
只能不断通过next()
函数实现按需计算下一个数据,
所以Iterator
的计算是惰性的,
只有在需要返回下一个数据时它才会计算。
Iterator
甚至可以表示一个无限大的数据流,
例如全体自然数。
而使用list
是永远不可能存储全体自然数的。
生成器(generator)
都是Iterator对象,
但list、dict、str
虽然是Iterable
,
却不是Iterator
。
把list、dict、str
等Iterable
变成Iterator
可以使用iter()
函数:
>>> isinstance(iter([]),Iterator)
True
>>> isinstance( iter('abc'),Iterator)
True
Python的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
3.itertools模块
python的内置模块itertools
提供了用于操作迭代对象的函数,
非常方便实用。
举一个例子:
islice(iterable, [start, ] stop [, step]):
创建一个迭代器,
生成项的方式类似于切片返回值:
iterable[start : stop : step],
将跳过前start个项,迭代在stop所指定的位置停止
step指定用于跳过项的步幅。
与切片不同,
负值不会用于任何start
,stop
和step
,
如果省略了start
,迭代将从0开始,
如果省略了step
,步幅将采用1.
from itertools import islicedef fib():a, b = 0,1while True:yield aa, b = b,a + bf = fib()
print (list(islice(f,10)))#[0,1,1,2,3,5,8,13,21,34]python学习交流扣扣qun:903971231