2016-05-23 5 views
5

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

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 

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

+6

Ваш '__iter__' должен возвращать итератор по картам, а не по длине. – kindall

+1

Возможный дубликат [Как сделать класс итерабельным?] (Http://stackoverflow.com/questions/19151/how-to-make-class-iterable) –

+1

@Rogalski Я не согласен, что это дубликат, это неочевидно, что делая его итерабельным, решает проблему с распаковкой (хотя и делает). –

ответ

6

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

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

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

Часто звезда-распаковка называется «итерируемая распаковка» по этой причине. См. PEP 448 (Additional Unpacking Generalizations) и PEP 3132 (Extended Iterable Unpacking).

Редактировать: Похоже, это было fixed for python 3.5.2 and 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 
+0

Эта ошибка была исправлена ​​в январе! https://github.com/python/cpython/blob/1123d9a07b4ab916e4d800308053980bcf8dbd57/Python/ceval.c#L5038-L5039 –