Звезда распаковка для собственных классов

Мне было интересно, можно ли использовать распаковку по звездам с собственными классами, а не просто со встроенными list а также tuple,

class Agent(object):
    def __init__(self, cards):
        self.cards = cards
    def __len__(self):
        return len(self.cards)
    def __iter__(self):
        return self.cards

И уметь писать

agent = Agent([1,2,3,4])
myfunc(*agent)

Но я получаю:

TypeError: visualize() argument after * must be a sequence, not Agent

Какие методы мне нужно реализовать, чтобы сделать возможной распаковку?

1 ответ

Решение

Сообщение об исключении:

аргумент после * должен быть последовательностью

должен действительно сказать, argument after * must be an iterable,

По этой причине часто распаковка звезд называется "повторяемой распаковкой". См. PEP 448 (Дополнительные обобщения распаковки) и PEP 3132 (Расширенная повторяемая распаковка).

Изменить: Похоже, это было исправлено для Python 3.5.2 и 3.6. В будущем он скажет:

аргумент после * должен быть повторяемым


Для того, чтобы распаковать звездочку, ваш класс должен быть повторяемым, то есть он должен определять __iter__ который возвращает итератор:

class Agent(object):
    def __init__(self, cards):
        self.cards = cards
    def __len__(self):
        return len(self.cards)
    def __iter__(self):
        return (card for card in self.cards)

затем:

In [11]: a = Agent([1, 2, 3, 4])

In [12]: print(*a)  # Note: in python 2 this will print the tuple
1 2 3 4
Другие вопросы по тегам