2016-05-23 12 views
5

Ich frage mich, ob es möglich ist, Star-Entpacken mit eigenen Klassen statt nur eingebauten wie list und tuple zu verwenden.star entpacken für eigene Klassen

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

Und in der Lage sein, schreiben

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

Aber ich bekomme:

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

Welche Methoden muss ich umsetzen, um möglich zu machen Auspacken?

+6

Ihr '__iter__' sollte einen Iterator über Ihre Karten zurückgeben, nicht deren Länge. – kindall

+1

Mögliche Duplikate von [Wie Klasse iterierbar machen?] (Http://stackoverflow.com/questions/19151/how-to-make-class-iterable) –

+1

@Rogalski Ich stimme nicht zu, das ist ein Duplikat, es ist nicht offensichtlich, dass es iterierbar zu machen löst das Problem des Star-Entpackens (obwohl es das tut). –

Antwort

6

Die Meldung Ausnahme:

Argument nach * muss eine Sequenz sein

sollte wirklich sagen, argument after * must be an iterable.

Oft wird aus diesem Grund "iterable entpacken" Star-Entpacken genannt. Siehe PEP 448 (Additional Unpacking Generalizations) und PEP 3132 (Extended Iterable Unpacking).

Bearbeiten: Sieht aus wie dies fixed for python 3.5.2 and 3.6 war. In Zukunft wird es sagen:

Argument nach * muss eine sein iterable


Um Stern auspacken zu haben, müssen Sie Ihre Klasse eine iterable dh sein muss es eine __iter__ definieren, die zurückgibt ein Iterator:

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) 

dann:

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

Dieser Fehler wurde im Januar behoben! https://github.com/python/cpython/blob/1123d9a07b4ab916e4d800308053980bcf8dbd57/Python/ceval.c#L5038-L5039 –