我对Python很新,只是看一些定义迭代器对象的例子。
我看到的例子是:
class fibit: # iterate through fibonacci sequence from 0,1...n<=max
def __init__(self, max):
self.max = max
def __iter__(self):
self.a = 0
self.b = 1
return self
def next(self):
fib = self.a
if fib > self.max:
raise StopIteration
self.a, self.b = self.b, self.a + self.b
return fib
但是,如果我将self.a和self.b的初始化从 iter 移动到 init ,似乎(我的简单理解)以完全相同的方式工作。
class fibit: # iterate through fibonacci sequence from 0,1...n<=max
def __init__(self, max):
self.a = 0
self.b = 1
self.max = max
def __iter__(self):
return self
def next(self):
fib = self.a
if fib > self.max:
raise StopIteration
self.a, self.b = self.b, self.a + self.b
return fib
那么推荐的方法是哪一个?
感谢。 :)
答案 0 :(得分:7)
初始化应在__init__
中完成。这就是它存在的原因。
Python中的迭代器对象规范地“使用一次” - 一旦你迭代了迭代器,就不会期望你能够再次迭代它。
因此,如果尝试再次迭代对象,则重新初始化值是没有意义的。为了说明这一点,我已经扩展了你的代码:
class fibit_iter: # iterate through fibonacci sequence from 0,1...n<=max
def __init__(self, max):
self.max = max
def __iter__(self):
self.a = 0
self.b = 1
return self
def next(self):
fib = self.a
if fib > self.max:
raise StopIteration
self.a, self.b = self.b, self.a + self.b
return fib
class fibit_init: # iterate through fibonacci sequence from 0,1...n<=max
def __init__(self, max):
self.a = 0
self.b = 1
self.max = max
def __iter__(self):
return self
def next(self):
fib = self.a
if fib > self.max:
raise StopIteration
self.a, self.b = self.b, self.a + self.b
return fib
iter_iter = fibit_iter(10)
iter_init = fibit_init(10)
print "iter_iter"
for item in iter_iter:
print item
break
for item in iter_iter:
print item
break
print "iter_init"
for item in iter_init:
print item
break
for item in iter_init:
print item
break
基本上,我从init版本创建一个对象,从iter版本创建一个对象。然后我尝试两次迭代两次。注意你是如何得到不同的结果的:
iter_iter
0
0
iter_init
0
1
答案 1 :(得分:1)
__init__
。它用于设置类实例的属性。
__iter__
用于定义可迭代的类的行为(返回一个交互器)。
@mgilson - __iter__
通常返回一个Iterator,它与列表不同(type()是物理上不同的),因为Iterators产生(破坏性消耗)值。
尝试调用xrange实例的__iter__()
方法,并尝试多次遍历这些值。
>>> foo = xrange(5)
>>> bar = a.__iter__()
>>> bar.next()
0
>>> bar.next()
1
>>> list(bar)
[2, 3, 4]
答案 2 :(得分:0)
这实际上取决于你希望你的迭代器做什么。如果你有充分的理由多次遍历迭代器,每次得到相同的结果,那么将初始化放在__iter__
;但是,这应该是例外,而不是常态;表现良好的迭代器在耗尽时应继续raise StopIteration
,而不是重新启动序列。实际上:在引发StopIteration
之后返回更多值的迭代器是considered broken(尽管这更像是一个警告,要小心你如何使用它)。
所以,重申:
对于标准迭代器,将初始化放在__init__
了解自定义/重复行为,将初始化设置为__iter__