我用4种方法制作了一个可迭代的Squares对象。经典的类,生成器样式以及有趣的是闭包样式和改进的(?)闭包样式。
课程
class Squares:
def __init__(self, n):
self.n = n
def __iter__(self):
return self.SquaresIterator(self.n)
class SquaresIterator:
def __init__(self, n):
self.n = n
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
result = self.i ** 2
self.i += 1
return result
它按预期工作
sq_class = Squares(5)
list(sq_class)
[0, 1, 4, 9, 16]
# calling again will create a new iterator
list(sq_class)
[0, 1, 4, 9, 16]
发电机
def squares(n):
for i in range(n):
yield i ** 2
sq_gen = squares(5)
list(sq_gen)
[0, 1, 4, 9, 16]
# calling again will return empty [] is OK, generator exhausted.
list(sq_gen)
[]
关闭
def Squares(n):
def inner():
return squares_gen(n)
def squares_gen(n):
for i in range(n):
yield i ** 2
return inner
sq_closure = Squares(5)
list(sq_closure())
[0, 1, 4, 9, 16]
# calling again the inner will create a new generator so it is not exhausted
list(sq_closure())
[0, 1, 4, 9, 16]
改进的(?)结束
def Squares(n):
def inner():
return squares_gen(n)
def squares_gen(n):
for i in range(n):
yield i ** 2
inner.__iter__ = lambda : squares_gen(n)
return inner
sq_closure = Squares(5)
list(sq_closure)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-beb02e61ccfb> in <module>
----> 1 for i in sq:
2 print(i)
TypeError: 'function' object is not iterable
我想尝试的是将__iter__
函数附加到内部函数对象上并返回一个生成器,然后我可以离开()-s并且可以将返回的内部函数用作可迭代对象。
可迭代协议的确切定义是什么?似乎仅存在__iter__
函数是不够的。
答案 0 :(得分:2)
“可迭代协议的确切定义” is in the documentation:
可迭代: 一个能够一次返回其成员的对象。可迭代的示例包括您使用
__iter__()
方法或实现序列语义的__getitem__()
方法定义的任何类的(...)对象。
但是:__magicmethods__
是only invoked when defined on the class-您不能基于实例覆盖它们(可以,但是不会被调用)。