我有以下点类:
import math
class Point:
"""Two-Dimensional Point(x, y)"""
def __init__(self, x=0, y=0):
# Initialize the Point instance
self.x = x
self.y = y
# def __iter__(self):
# return iter(int(self.x))
# return iter(int(self.y))
return self
@property
def magnitude(self):
# """Return the magnitude of vector from (0,0) to self."""
return math.sqrt(self.x ** 2 + self.y ** 2)
def distance(self, self2):
return math.sqrt((self2.x - self.x) ** 2 + (self2.y - self.y) ** 2)
def __str__(self):
return 'Point at ({}, {})'.format(self.x, self.y)
def __repr__(self):
return "Point(x={},y={})".format(self.x, self.y)
我想让“点”可迭代,以便以下是可能的:
point = Point(2, 3)
x, y = point
print(x)
2
print(y)
3
如果你看到我的注释代码,这就是我尝试的,但它说 TypeError: iter() 返回了类型为“Point”的非迭代器。关于如何正确执行此操作的任何想法?
tl;博士:
def __iter__(self):
yield self.x
yield self.y
为了使某些东西可迭代,你需要你的__iter__
方法来返回一个迭代器。
你不能只是return self
, 除非self
已经是一个迭代器(这意味着它有一个__next__
方法)。但是你不想points
成为一个迭代器,你希望它可以一遍又一遍地迭代。
return iter(int(self.x))
那么你不能return iter(int(self.y))
,有两个原因。首先,在你之后return
,你的功能就完成了;之后发生的任何代码都不会运行。其次,你可以不叫iter
上int
。(此外,还有没有理由骂int
上int
。)
您可以通过从 each 创建一个可迭代对象来解决最后一组问题int
,例如单元素列表,迭代该可迭代对象,然后使用yield from
代替委托给它return
。在函数中使用yield
oryield from
使其成为生成器函数,生成函数创建的生成器是迭代器:
yield from iter([self.x])
yield from iter([self.y])
……但这有点傻。一旦我们知道我们想要一个生成器,我们就可以只yield
迭代我们想要迭代的值。因此,顶部的代码。
或者,您可以为两个元素显式创建一个单元素可迭代对象并将它们链接在一起并返回:
def __iter__(self):
return itertools.chain(iter([self.x]), iter([self.y]))
但这也很愚蠢。在单元素列表上链接两个迭代器与仅迭代一个双元素列表相同:
def __iter__(self):
return iter([self.x, self.y])
最后,与其依赖于chain
Python 自带的生成器、列表迭代器、或其他迭代器类型,您始终可以明确地编写一个:
class PointIterator:
def __init__(self, point):
self.values = [point.x, point.y]
def __next__(self):
try:
return self.values.pop(0)
except IndexError:
raise StopIteration
def __iter__(self):
return self
class Point:
# ... other code
def __iter__(self):
return PointIterator(self)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句