2015-06-07 18 views
7

Questo funziona e felicemente stamperà 81:Perché `classe X: mypow = pow` funziona? Che dire di "sé"?

class X: 
    mypow = pow 

print(X().mypow(3, 4)) 

Ma perché? Non è il metodo dato l'argomento extra di "sé" e dovrebbe essere completamente confuso?

Per confronto, ho anche provato con la mia Pow funzione:

def Pow(x, y, z=None): 
    return x ** y 

class Y: 
    myPow = Pow 

print(Pow(3, 4)) 
print(Y().myPow(3, 4)) 

la funzione Direct stampe chiamate 81 e si blocca il metodo di chiamata come previsto, come fa ottenere tale argomento esempio in più:

Python 3: TypeError: unsupported operand type(s) for ** or pow(): 'Y' and 'int' 
Python 2: TypeError: unsupported operand type(s) for ** or pow(): 'instance' and 'int' 

Perché/come funziona Python possedere pow lavoro qui? The documentation non ha aiutato e non ho trovato la fonte.

+0

Lo stesso modo in cui viene passato al mio 'Pow'? @PadraicCunningham –

+1

Questo perché l'attributo '__self__' delle funzioni builtin non è scrivibile, quindi è sempre' None' per 'pow'. –

+0

@vaultah Prova in Python 2. –

risposta

5

Ciò è dovuto al fatto che le funzioni python definite in C (builtins) hanno argomenti auto gestiti automaticamente. Ecco l'intestazione della funzione Pow:

static PyObject * math_pow(PyObject *self, PyObject *args) Qui puoi vedere che il sé è sempre passato dall'interprete.

+0

Non è' math.pow', non 'pow'? –

+0

È math.pow, ma il comportamento è lo stesso. –

+0

Hmm, ho controllato e confermato che si comporta allo stesso modo (cioè restituisce felicemente 81.0). Ho trovato [la fonte di questo] (https://github.com/python-git/python/blob/master/Modules/mathmodule.c#L927) e ignora semplicemente l'argomento 'self'. Credo che avrei bisogno di sapere come i metodi definiti dall'utente * non * lo ignorino per capirlo veramente. AshwiniChaudhary ha anche commentato qualcosa su '__self__' di builtin, che ho confermato, ma suppongo che non dovrebbe importare se non viene comunque utilizzato.Guarderò un po 'in entrambi i problemi. –

2

Questo comportamento è collegato a method binding. Date un'occhiata a ciò che Python vi racconta queste funzioni/metodi:

>> pow 
<built-in function pow> 
>>> X.mypow 
<built-in function pow> 
>>> X().mypow 
<built-in function pow> 

e

>>> Pow 
<function Pow at 0x7f88f5715f50> 
>>> Y.myPow 
<unbound method Y.Pow> 
>>> Y().myPow 
<bound method Y.Pow of <__main__.Y instance at 0x7f88f57117e8>> 

Inoltre gli stati di documentazione:

metodi negozio dizionari di classe come funzioni. In una definizione di classe, i metodi vengono scritti utilizzando def e lambda, i soliti strumenti per la creazione di funzioni. [...]

Per supportare le chiamate di metodo, le funzioni includono il metodo __get__() per i metodi di associazione durante l'accesso agli attributi. Ciò significa che tutte le funzioni sono descrittori non di dati che restituiscono metodi associati o non associati a seconda che siano invocati da un oggetto o una classe. [...]

ma le funzioni built-in non hanno un metodo __get__(). Ecco perché pow non era vincolato e poteva essere usato nel modo in cui lo hai osservato, mentre il Pow non poteva.