>>> for x in5: ... print(x) ... Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object isnot iterable
那我们怎么知道它先去找__iter__()呢?我们在前面的代码里加上几行,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
from collections.abc import Iterator from collections.abc import Iterable classmylist1: def__init__(self, l): self.l = l def__getitem__(self, i): return self.l[i] def__iter__(self): return self print(isinstance(a, Iterable)) print(isinstance(a, Iterator)) a = mylist1([1,2,3]) for x in a: print(x)
结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
True False Traceback (most recent call last):
File "<ipython-input-13-8e65b9d361a6>", line 1, in <module> runfile('C:/Users/xlniu/test123/test.py', wdir='C:/Users/xlniu/test123')
File "C:\Users\xlniu\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 827, in runfile execfile(filename, namespace)
File "C:\Users\xlniu\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/xlniu/test123/test.py", line 49, in <module> for x in a:
TypeError: iter() returned non-iterator of type 'mylist1'
生成器的来源主要有两个,一个是生成器表达式,例如(i for i in ‘hello, world’), (i for i in range(0,10) if i % 2 == 0),另一个是生成器函数,生成器函数不使用return返回数据,而使用yield。
我们来看一下前面说的filter是不是生成器。
1 2 3 4 5 6 7
>>> from collections.abc import Iterator >>> from collections.abc import Iterable >>> from collections.abc import Generator >>> a = [1,2,3,4,5,6] >>> b = filter(lambda x : x % 2 == 0, a) >>> print(isinstance(b, Generator)) False
>>> from collections.abc import Generator >>> a = (i for i in range(0, 10)) >>> next(a) 0 >>> next(a) 1 >>> print(isinstance(a, Generator)) True >>> print(type(a)) <class 'generator'> >>> print(a) <generatorobject <genexpr> at 0x000001A61011B7C8> #通过genexpr得到的生成器 >>> b = (i.upper() for i in 'hello, world') >>> c = (x for x in range(0,10) if x % 5 == 0) >>> for x in b: ... print(x) ... H E L L O ,
W O R L D >>> d = [i for i in range(0,10)] >>> print(type(d)) >>> type(d) <class 'list'> >>> print(d) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
如果我们把生成器表达式用在其他的对象上,例如set,list等,它们会自动转换成相应类型。
1 2 3 4 5 6 7 8
>>> set(i for i in range(0,5)) # 相当于set( (i for i in range(0,5)) ) {0, 1, 2, 3, 4} >>> set( (i for i in range(0,5)) ) {0, 1, 2, 3, 4} >>> tuple(i for i in range(0,5)) (0, 1, 2, 3, 4) >>> list(i for i in range(0,5)) [0, 1, 2, 3, 4]
from collections.abc import Iterator from collections.abc import Iterable from collections.abc import Generator
defmyrange(stop): i = 0 while i < stop: yield i #返回i,下次调用时会从这个地方继续向下执行 i += 1 e = myrange(5) print(isinstance(e, Iterable)) print(isinstance(e, Iterator)) print(isinstance(e, Generator)) print(type(e)) print(e) print(next(e)) for x in e: print(x)