2011-09-20 10 views
5

Sé que si desea agregar un método a una instancia de clase no se puede hacer una asignación simple como esto:python3: vincular el método a la instancia de clase con .__ get __(), funciona, pero ¿por qué?

>>> def print_var(self): # method to be added 
     print(self.var) 
>>> class MyClass: 
     var = 5 
>>> c = MyClass() 
>>> c.print_var = print_var 

este hecho provocaría print_var a comportarse como una función normal, por lo que el argumento self wouldn 't tienen su típica significado:

>>> c.print_var 
<function print_var at 0x98e86ec> 
>>> c.print_var() 
Traceback (most recent call last): 
    File "<pyshell#149>", line 1, in <module> 
    c.print_var() 
TypeError: print_var() takes exactly 1 argument (0 given) 

el fin de permitir la función de ser considerado como un método (es decir, para obligar a éste a la instancia), I utilizado para utilizar este código:

>>> import types 
>>> c.print_var = types.MethodType(print_var, c) 
>>> c.print_var 
<bound method MyClass.print_var of <__main__.MyClass object at 0x98a1bac>> 
>>> c.print_var() 
5 

pero he encontrado que .__get__ también se pueden usar para este propósito:

>>> c.print_var = print_var.__get__(c) 
>>> c.print_var 
<bound method MyClass.print_var of <__main__.MyClass object at 0x98a1bac>> 
>>> c.print_var() 
5 

El problema aquí es que simplemente funciona, pero no puedo entender cómo y por qué. La documentación sobre .__get__ no parece ayudar mucho.

Agradecería que alguien pudiera aclarar este comportamiento del intérprete de Python.

Respuesta

5

La información que está buscando es en el Descriptor HowTo Guide:

Para apoyar las llamadas a métodos, funciones incluyen el método __get__() para los métodos de unión durante el acceso atributo. Esto significa que todas las funciones son descripciones que no son de datos que devuelven métodos vinculados o no dependientes, dependiendo de si se invocan desde un objeto o una clase. En Python puro, funciona así:

class Function(object): 
    . . . 
    def __get__(self, obj, objtype=None): 
     "Simulate func_descr_get() in Objects/funcobject.c" 
     return types.MethodType(self, obj, objtype) 

Así que en realidad no hay nada extraño está pasando - el método de un objeto función __get__ llama types.MethodType y devuelve el resultado.

+1

En Python 3 'MethodType()' solo acepta 2 argumentos. – joeforker

+0

@joeforker Estoy citando de los documentos de Python allí, parece que necesitan ser actualizados. – agf

Cuestiones relacionadas