@[TOC](理解Python Container(容器)、可迭代对象(iterable)、迭代器(iterable)、生成器(generator))
首先通过一张图来进行理解:
1.容器
容器你可以把它看作存储糖果的罐子,糖果就是罐子里面的元素。所有的容器都放在一个存储室(内存)中。一些常见的容器:
list, deque.....
set,frozensets,....
dict, defaultdict, OrderedDict, Counter, .....
tuple, namedtuple,...
str
...
大多数的容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身具有的能力,而是可迭代对象赋予了容器这种能力。
2. 可迭代对象(iterable)
大多数常见的容器都是可迭代对象,还有其他的一些非容器类型也是可迭代对象,比如处于打开状态的files, sockets。可以返回迭代器的对象都可以称为可迭代对象。
x = dict(a=1,b=2,c=3)
y = iter(x)
z = iter(x)
print(next(y))
print(next(z))
print(next(y))
print(next(z))
print(type(x))
print(type(y))
print(type(z))
"""
a
a
b
b
<class 'dict'>
<class 'dict_keyiterator'>
<class 'dict_keyiterator'>
"""
可迭代对象在实现了__iter__方法后
就是一个迭代器。
3.迭代器
迭代器iterator是一个带有状态的对象,在调用next()方法的时候返回容器中的下一个值,任何实现了__iter__方法和__next__()方法的对象都是迭代器,__iter__返回迭代器本身,next()返回容器的下一个值,如果容器中没有更多的元素进行访问,则抛出StopIteration异常。
class Fib:
def __init__(self):
self.prev = 0
self.curr = 1
def __iter__(self):
return self
def __next__(self):
value = self.curr
self.curr += self.prev
self.prev = value
return value
f = Fib()
##sclice第一个参数是一个可迭代的对象,返回值是迭代器切片,这里就是返回Fib()这个迭代器内部0-10位的数值
list(islice(f, 0, 10))
"""
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
"""
4.生成器
生成器是一种迭代方式更加优雅的迭代器。它不需要实现__iter__和__next__()方法,只需要一个yiled关键字。一个生成器一定是迭代器,
def fib():
prev, curr = 0, 1
while True:
yield curr
prev, curr = curr, curr + prev
f = fib()
list(islice(f, 0, 10))
"""
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
"""
当代码执行f=fib(),返回的是一个生成器对象,这个时候内部代码并没有执行,只有显示或者隐式的调用next()再回执行里面的代码。
生成器在Python中是一个非常强大的编程结构,可以用更少地中间变量写流式代码,此外,相比其它容器对象它更能节省内存和CPU,当然它可以用更少的代码来实现相似的功能。
a = [x**2 for x in range(10)]
print(a)
a = (x**2 for x in range(10))
print(a)
"""
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x7f22ed497820>
"""