我一直在尝试将矢量数学库移植到Transcrypt,但我遇到了模拟可迭代类型的问题。
我有一个带有内部可迭代对象的 Vector 类。 以下是核心的简化版本:
class Vector:
def __init__(self, *values):
self.values = values
def __iter__(self):
for item in self.values:
yield item
def __add__(self, other):
return Vector( *(x + y for x, y in zip(self, other)))
在纯python中,(Vector(1,2,3) + Vector(3,4,5))
如您所期望的那样返回Vector(4,6,8)
。但是在转译之后,同样的代码失败了——在Javascript中,zip()
似乎期待Javascript map()
在其可迭代对象上运行。
在这种情况下,我可以通过显式针对底层存储来解决它,因为它是使用 *args 创建的 - 似乎具有所需的方法:
def __add__(self, other):
pairwise = zip(self.values, other.values)
return Vector( *(itertools.starmap(lambda a, b: a + b, pairwise)))
但是将其耦合到内部容器对我来说感觉摇摇欲坠,我认为创建迭代器和星图有开销。
那么,解决这个问题的正确方法是什么? 我可以在课程中添加map()
吗?如果是这样,正确的签名是什么?底层 JS 似乎依赖于 JS 范围行为......吓死我了...
关键是zip
尚未适应迭代器。一个简单的解决方法是将zip
的参数转换为列表。以下代码有效:
class Vector:
def __init__(self, *values):
self.values = values
def __iter__(self):
for item in self.values:
yield item
def __add__(self, other):
return Vector( *(x + y for x, y in zip(list (self), list (other))))
def __str__ (self):
return self.values
#__pragma__ ('opov')
print (Vector(1,2,3) + Vector(3,4,5))
#__pragma__ ('noopov')
这将打印:
4,6,8
抱歉回答晚了,这几个月有点分散。为迭代器调整zip我发现相当复杂,这就是为什么它还没有完成。
想想看,将参数转换为列表可以自动完成。我将添加它(问题 #369(,尽管运行时测试的开销(很小(,因为它更好地匹配预期的行为。
它在 3.6.44 版本中,您的代码现在应该无需更改即可正常工作(使用 -e 6 开关激活迭代器(。