我正在研究制作可迭代的对象,并且我想知道这两个选项中哪一个更加pythonic /更好的方式,没有区别或者我对使用yield有错误的想法?对我来说使用yield似乎更清晰,显然它比使用__next __()更快,但我不确定.
class iterable_class():
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i < self.n:
i = self.i
self.i += 1
return i
else:
raise StopIteration()
Run Code Online (Sandbox Code Playgroud)
使用产量:
class iterable_class_with_generator():
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
while self.i < self.n:
yield self.i
self.i += 1
Run Code Online (Sandbox Code Playgroud)
一个可观察到的区别是第一个版本实现了一个迭代器(一个拥有__next__并__iter__返回其自身的对象),而第二个实现了一个迭代(一个可以实现__iter__创建一些迭代器的对象).在大多数情况下,这并没有什么区别,因为for语句和所有itertools都接受任何迭代.
使用以下代码可以看出差异:
>>> x = iterable_class(10)
>>> next(x)
0
>>> next(x)
1
>>> list(x)
[2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
显然这不起作用,iterable_class_with_generator因为它没有实现__next__.但是有一个更深层次的区别:因为list(x)接受任何可迭代的,它将首先调用x.__iter__(),这将在iterable_class_with_generator创建一个新的生成器的情况下从头开始计数.在答案的最后给出了一个真正的基于生成器的迭代器,但在大多数情况下,差异无关紧要.
关于是使用生成器还是定义自己的样式的样式差异__next__,两者都将被识别为正确的Python,因此您应该选择能够更好地维护代码的人或团队.由于生成器版本较短,生成器是一个易于理解的Python习语,我会选择那个.
请注意,如果__iter__使用生成器实现,则不需要在实例变量中保持迭代状态,因为生成器会为您执行此操作.然后代码更简单:
class iterable_class_with_generator:
def __init__(self, n):
self.n = n
def __iter__(self):
for i in range(self.n):
yield i
Run Code Online (Sandbox Code Playgroud)
iterable_class_with_generator实现了一个在内部使用生成器的真正的迭代器:
class iterable_class_with_generator:
def __init__(self, n):
self._gen = self._generate(n)
def __iter__(self):
return self
def __next__(self):
return next(self._gen)
def _generate(self, n):
for i in range(n):
yield i
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
122 次 |
| 最近记录: |