Итеративная эмуляция в транскрипте
Я пытался портировать библиотеку векторной математики для транскрипции и столкнулся с проблемой эмуляции итерируемых типов.
У меня есть класс 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)))
В чистом питоне (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 scoping поведение... что пугает меня...
1 ответ
Дело в том, что 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 для активации итераторов).