2014-06-11 12 views
10
>>> class Potato(object): 
...  def method(self, spam): 
...   print self, spam 
... 
>>> spud = Potato() 

Works:Perché non possiamo ** unsplat 'self' in un metodo?

>>> Potato.method(spud, **{'spam': 123}) 
<__main__.Potato object at 0x7f86cd4ee9d0> 123 

non funziona:

>>> Potato.method(**{'self': spud, 'spam': 123}) 
# TypeError 

Ma perché no? Pensavo che il 'sé' fosse solo una convenzione, e non c'era nulla di intrinsecamente speciale in questo argomento? instancemethod oggetto wrapper di

+3

Questa è una domanda interessante. Un pensiero: la convenzione è che "io" è il primo argomento, non che si chiama "sé". Forse non si aspetta di essere spacchettato per nome, ma per posizione – slezica

+1

Si ottiene lo stesso problema con 'Potato.method (self = spud, spam = 123)'. Lo splat non è davvero il problema. –

+1

È proprio perché "io" è solo una convenzione che non puoi fare questo. Poiché il nome 'self' non ha uno stato speciale, Python conosce solo quale argomento è' self' perché è * primo * nella lista degli argomenti, quindi deve essere passato in modo posizionale. – BrenBarn

risposta

12

Python 2 insiste sulla ispezionare il primo argomento posizionale, e che il check non supporta argomenti chiave, punto fermo:

>>> Potato.method(self=spud, spam=123) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unbound method method() must be called with Potato instance as first argument (got nothing instead) 

Si noti che non ho usato argomento disimballaggio lì!

È possibile utilizzare gli argomenti di posizione più che bene:

>>> Potato.method(*(spud,), **{'spam': 123}) 
<__main__.Potato object at 0x1002b57d0> 123 

oppure si può accedere all'oggetto funzione originale:

>>> Potato.method.__func__(**{'self': spud, 'spam': 123}) 
<__main__.Potato object at 0x1002b57d0> 123 

per aggirare questa limitazione.

Python 3 non utilizza più un wrapper del metodo per i metodi non associati; la funzione sottostante viene invece restituita direttamente.

+0

Codice di riferimento: http://hg.python.org/cpython/file/9438a8aa3622/Objects/classobject.c#l2548 Si noti' self = PyTuple_GET_ITEM (arg, 0); 'su linea 2561 senza alcun tentativo di controllare il dict 'kw'. – user2357112

+0

@ user2357112: e perché * dovrebbe * it? Dovrebbe introspettare la funzione unwrapped per vedere quale sia il nome del primo argomento, il tutto per supportare un estremo edge-case facilmente aggirato semplicemente scartando invece l'oggetto metodo. –

+0

Questo è solo un dettaglio di implementazione cpython? Sarebbe ancora chiamato "python" se si _did_ scavasse nei kwargs per cercare un kwarg che corrisponda al nome dell'argomento del primo argomento in argspec? _edit: _ la risposta a questa domanda è indirizzata nel duplicato collegato. – wim