Lo primero es conseguir los nombres correctamente:
>>> def increment(obj):
... obj.count += 1
...
>>> class A(object):
... def __init__(self):
... self.count = 0
...
>>> o = A()
>>> o.__init__
<bound method A.__init__ of <__main__.A object at 0x0000000002766EF0>>
>>> increment
<function increment at 0x00000000027797C8>
nombres propios son Así funciones y Métodos vinculados. Ahora se puede buscar la manera de Bind an Unbound Method y es probable que el resultado final será la lectura sobre descriptors:
En general, un descriptor es un atributo de objeto con " comportamiento de enlace", uno cuyo acceso atributo se ha reemplazado por métodos en el protocolo descriptor Esos métodos son __get__
, __set__
y __delete__
. Si alguno de esos métodos está definido para un objeto, se dice que es un descriptor.
Puede transformar fácilmente la función de método simplemente usando diferentes invocación de __get__
>>> increment.__get__(None, type(None))
<function increment at 0x00000000027797C8>
>>> increment.__get__(o, type(o))
<bound method A.increment of <__main__.A object at 0x00000000027669B0>>
y funciona como un encanto:
>>> o = A()
>>> increment.__get__(None, type(None))(o)
>>> o.count
1
>>> increment.__get__(o, type(o))()
>>> o.count
2
Usted puede agregar fácilmente estos métodos recién delimitadas a objetos:
def increment(obj):
obj.count += 1
def addition(obj, number):
obj.count += number
class A(object):
def __init__(self):
self.count = 0
o = A()
o.inc = increment.__get__(o)
o.add = addition.__get__(o)
print(o.count) # 0
o.inc()
print(o.count) # 1
o.add(5)
print(o.count) # 6
O puede crear su propia descriptor que se va a convertir función a método vinculado:
class BoundMethod(object):
def __init__(self, function):
self.function = function
def __get__(self, obj, objtype=None):
print('Getting', obj, objtype)
return self.function.__get__(obj, objtype)
class B(object):
def __init__(self):
self.count = 0
inc = BoundMethod(increment)
add = BoundMethod(addition)
o = B()
print(o.count) # 0
o.inc()
# Getting <__main__.B object at 0x0000000002677978> <class '__main__.B'>
print(o.count) # 1
o.add(5)
# Getting <__main__.B object at 0x0000000002677978> <class '__main__.B'>
print(o.count) # 6
Y también se puede ver que esto es bien consistente con function/bound method principles:
Clase los diccionarios almacenan métodos como funciones. En una definición de clase, los métodos se escriben usando def y lambda, las herramientas usuales para crear funciones. La única diferencia con las funciones normales es que el primer argumento está reservado para la instancia del objeto. Según la convención de Python, la referencia de instancia se llama self pero se le puede llamar este o cualquier otro nombre de variable.
Para admitir llamadas de método, las funciones incluyen el método __get__()
para métodos de enlace durante el acceso de 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.
Y funciones se convierte en método vinculado durante la inicialización de instancia:
>>> B.add
# Getting None <class '__main__.B'>
<function addition at 0x00000000025859C8>
>>> o.add
# Getting <__main__.B object at 0x00000000030B1128> <class '__main__.B'>
<bound method B.addition of <__main__.B object at 0x00000000030B1128>>
he tenido este problema tratando de construir una clase Heapq utilizando el módulo 'heapq' feo. Tu solución es buena Se puede hacer en una línea, pero tiene la misma eficacia: 'def method_wraper (f): return functools.wraps (f) (lambda * a, ** kw: f (* a, ** kw))' – JBernardo
. ..Interesante, la asignación parece funcionar bien si la función se define dentro del mismo módulo (método independiente que se asigna a una clase y vinculado a creación de instancias). Entonces, ¿es solo un problema con las extensiones C o con funciones en diferentes módulos? De todos modos, es posible que desee comprobar http://stackoverflow.com/questions/7490879/python3-bind-method-to-class-instance-with-get-it-works-but-why, lo que podría ayudar un poco también. – JAB
Además, http://docs.python.org/py3k/howto/descriptor.html#functions-and-methods "la implementación C real de PyMethod_Type en Objects/classobject.c es un solo objeto con dos representaciones diferentes según si el campo im_self está establecido o es NULL (el equivalente en C de None). " Lo que hace que parezca que este problema no debería estar ocurriendo en absoluto, a menos que Python de alguna manera no actualice ese campo directamente para los métodos de un objeto al crear una instancia del objeto. – JAB