我有以下点类:
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() returned non-iterator of type '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 之后,您的功能就完成了;之后发生的任何代码都不会运行。其次,您不能在 int 上调用 iter。 (此外,没有理由在 int 上调用 int。)
您可以通过从每个 int 创建一个可迭代对象来解决最后一组问题,例如单元素列表,迭代该可迭代对象,然后使用 yield from< 委托(delegate)给它 而不是 return。在函数中使用 yield 或 yield 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)
