接触python迭代器,生成器后,查阅资料整理了一些知识点,写了一些自己的感悟,如有错误希望及时指正。
- 有一个列表,依次读取其中的值,就是迭代的意思,当一个对象是可以迭代的,可以使用for in 对其进行迭代。
list = [1, 2, 3]
for i in mylist:
print(i)
#result:
1
2
3
from collections import Iterable
print(isinstance([1, 2, 3], Iterable)) #true
print(isinstance({}, Iterable)) #true
print(isinstance(123, Iterable)) #false
print(isinstance('abc', Iterable)) #true
from collections import Iterator
print(isinstance([1, 2, 3], Iterator)) #false
print(isinstance({}, Iterator)) #false
print(isinstance(123, Iterator)) #false
print(isinstance('abc', Iterator)) #false
可以看出list、dict和str都是可迭代的。但是他们并不是迭代器。
- 可以被next()函数调用并不不断返回下一个值得对象称为迭代器:Iterator,迭代器有一个特性,惰性计算。惰性计算指的是在调用时才会计算值,它可以避免不必要的计算,带来性能的提,并且能够节省内存空间。在下面生成器的例子中,更加具体的介绍了这一个特性。
生成器是可以迭代的,但是你只可以读取它一次 ,因为它并不把所有的值放在内存中,它是实时地生成数据;
下面的代码中,生成器表达式和列表解析语法相似,只不过把列表解析的[]换成()。生成器表达式能够做的事情,列表解析很多也是能够胜任的,但是相较于较大的数据序列时,生成器的优势就能够体现出来,列表解析就会占用较大内存。在下面代码的第一行我们定义了一个g_generator,打印出来的类型显示是生成器,在定义时,系统并不会对其分配内存,在下面for in 循环时,才会真正的开始计算。
g_generator = (x * x for x in range(10))
print(type(g_generator)) #<class 'generator'>
print(isinstance(g_generator, Iterable)) #true
print(isinstance(g_generator, Iterator)) #true
for i in g_generator:
print(i)
#0
#1
#4
#9
#16
#25
#36
#49
#64
#81
在生成器中存在着next()和iter()方法,通过help(g_generator)来查看:
<genexpr> = class generator(object)
| Methods defined here:
|
| __del__(...)
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __iter__(self, /)
| Implement iter(self).
|
| __next__(self, /)
| Implement next(self).
|
| __repr__(self, /)
| Return repr(self).
|
| close(...)
| close() -> raise GeneratorExit inside generator.
|
| send(...)
| send(arg) -> send 'arg' into generator,
| return next yielded value or raise StopIteration.
|
| throw(...)
| throw(typ[,val[,tb]]) -> raise exception in generator,
| return next yielded value or raise StopIteration.
|
通过for in 循环和generator的next()方法,可以很容易的取想要得数,虽然上面g_generator有10个数,但是通过next()打印需要的5个数,后面的5个就没有被计算,极大的节省了内存。
for i in range(5):
print(next(g_generator))
#0
#1
#4
#9
#16
迭代是一个实现可迭代对象(实现 __iter__() 方法)和迭代器(实现 __next__() 方法)的过程。可迭代对象是你可以从其获取到一个迭代器的任一对象。迭代器是那些允许你迭代可迭代对象的对象。
- yield关键字,类似于return,作用是把一个函数变成一个 generator。下面通过举例Fibonacci数列来形象地解释。首先定义一个fib函数,python解释器会将函数中yield b 视作generator,我们通过打印fib()的类型来证明。调用fib(6)时,fib()函数并不会执行,而是返回了一个可迭代对象。在for循环执行时,才会执行。通过debug可以发现,每次循环都会执行 fib 函数内部的代码,执行到 yield b 时,fib 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,直到再次遇到 yield。同样我们可以调用next()方法来执行,3.X版本方法变为__next__()
def fib(x):
n, a, b = 0, 0, 1
while n < x:
yield b
a, b = b, a + b
n += 1
f = fib(6)
print(f) #<generator object fib at 0x000001B78B95BDB0>
print(type(f)) #<class 'generator'>
print(isinstance(f, Iterable)) #true
print(isinstance(f, Iterator)) #true
for i in f:
print(i)
#1
#1
#2
#3
#5
#8
ff = fib(6)
print(ff.__next__()) #1
print(ff.__next__()) #1
print(ff.__next__()) #2
参考内容:https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do