2016-02-10 23 views
6

Ho notato che se definisco un attributo di classe uguale a una funzione quando creo un'istanza di quella classe l'attributo diventa un metodo associato. Qualcuno può spiegarmi la ragione di questo comportamento?Python - funzione come attributo di classe diventa un metodo associato

In [9]: def func(): 
    ...:  pass 
    ...: 

In [10]: class A(object): 
    ....:  f = func 
    ....:  

In [11]: a = A() 

In [12]: a.f 
Out[12]: <bound method A.func of <__main__.A object at 0x104add190>> 

In [13]: a.f() 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-13-19134f1ad9a8> in <module>() 
----> 1 a.f() 
    global a.f = <bound method A.func of <__main__.A object at 0x104add190>> 

TypeError: func() takes no arguments (1 given) 

risposta

7

È stata assegnata una funzione all'attributo f. Perché la funzione è ora all'interno di una classe diventa un metodo, in particolare un metodo associato (perché è limitato all'oggetto, further explanation here).

Methods in classi ricevono almeno un parametro (self), meno che non sia espressamente detto di non - vedi class methods and static methods -, per questo motivo l'errore dice che func non prende argomenti (come è definita come def func():) ma ha ricevuto 1 (self)

di fare ciò che si vuole, si dovrebbe dire Python che si sta utilizzando un static method

def func(): 
    pass 

class A(object): 
    f = staticmethod(func) 
1

Python è non un sistema OO messaggio basato . Invece, simili a JavaScript, le proprietà vengono risolte in funzioni di prima classe e quindi invocate; il comportamento differisce un po 'nella meccanica di tali, come scoperto.

In Python il requisito è che i metodi hanno almeno un parametro, normalmente chiamato self, che sarà automaticamente fornito l'istanza associata quando viene invocato come metodo.

Inoltre (e forse fino al punto della domanda), Python non fa distinzione tra l'utilizzo di def f.. o f = some_func() quando si stabiliscono i collegamenti dei membri di istanza; probabilmente questo corrisponde al comportamento al di fuori delle classi.

Nell'esempio, l'assegnazione della funzione all'istanza "fa in modo che venga considerata come un metodo di istanza". È la stessa identica funzione senza parametri chiamata in entrambi i casi; solo l'uso futuro di tale è rilevante.

Ora, a differenza di JavaScript, Python gestisce i metodi e l'associazione degli oggetti tramite il concetto di metodi associati: funzioni risolte in quanto i metodi sono sempre "vincolati".

Il comportamento di a.f che restituisce un metodo associato, funzione che fornirà automaticamente l'oggetto associato al primo parametro come self, viene eseguito indipendentemente dall'origine della funzione. In questo caso, ciò significa che la funzione senza parametri non può essere utilizzata quando è "vincolata" poiché non accetta un parametro self.

A dimostrazione, la seguente fallirà nello stesso modo perché la fonte metodo sottostante non non soddisfano i requisiti minimi di accettare l'istanza come argomento:

g = a.f 
g() 

In questo caso chiamando g() è equivalente a chiamare func(a).


Per confronto, Java, C#, Ruby, e Smalltalk sono sistemi OO messaggi basati - in questi un oggetto viene detto di richiamare un metodo da un 'nome', invece di risolvere un metodo (o funzione) come valore che può essere invocato.