variable method may classes python instance-method

may - Agregando atributos a instancemethods en Python



static class python (2)

Me topé con este comportamiento al intentar que los decoradores de clases y los decoradores de métodos jugaran bien juntos. Esencialmente, los decoradores del método marcarían algunos de los métodos como especiales con algún valor ficticio, y el decorador de la clase vendría después y completaría el valor más adelante. Este es un ejemplo simplificado

>>> class cow: >>> def moo(self): >>> print ''mooo'' >>> moo.thing = 10 >>> >>> cow.moo.thing 10 >>> cow().moo.thing 10 >>> cow.moo.thing = 5 AttributeError: ''instancemethod'' object has no attribute ''thing'' >>> cow().moo.thing = 5 AttributeError: ''instancemethod'' object has no attribute ''thing'' >>> cow.moo.__func__.thing = 5 >>> cow.moo.thing 5

¿Alguien sabe por qué cow.moo.thing = 5 no funciona, aunque cow.moo.thing claramente me da 10? ¿Y por qué cow.moo.__func__.thing = 5 funciona? No tengo idea de por qué lo hace, pero al azar jugando con cosas en la lista de dir(cow.moo) tratando de hacer que algo funcione, de repente lo hizo, y no tengo idea de por qué.


Para la búsqueda de atributos, Python está utilizando automáticamente la función real adjunta al método de instancia.

Para la configuración de atributos, no lo es.

Son dos operaciones separadas según el lado de la declaración en la que se encuentre, aunque ambas usan el . operador.

Cuando accede al __func__ un método de __func__ , está accediendo manualmente a la función real que realmente tiene el atributo moo .

En Python 3, esto funcionará como le gustaría o esperaría, ya que los métodos son básicamente funciones.


Si está buscando modificar los atributos de función de ambas funciones y métodos de instancia desde C, debe verificar el tipo de llamada que tiene.

Entonces, asumiendo que tienes un PyObject de algún tipo de llamada, puedes verificarlo así:

PyObject *callable; // set to something callable PyObject *setting; // set to something if(PyMethod_Check(callable)){ PyObject_SetAttrString(PyMethod_Function(callable),"attribute",setting); }else{ PyObject_SetAttrString(callable,"attribute",setting); } ... // and the inverse if(PyMethod_Check(callable){ if(PyObject_HasAttrString(PyMethod_Function(callable),"attribute")){ PyObject_DelAttrString(PyMethod_Function(callable),"attribute"); } }else{ if(PyObject_HasAttrString(callable,"attribute")){ PyObject_DelAttrString(callable,"attribute"); } }

Ahora, el código agf señaló que funciona desde Python para los métodos de ejemplo. Si solo intento establecer el atributo del método de instancia, no encontrará el atributo, no importa cómo intenté acceder a él desde Python.

Me encontré con este problema y la pregunta de Li Haoyi con la respuesta de agf me ayudó a entender qué se necesitaba cambiar. Pensé que alguien encontraría esta pregunta y respondería de nuevo mientras buscaba cómo resolver este problema a través de C.

Edición: Nota: Esto es para Python 2.7.x. Python 3.x usa diferentes llamadas a funciones.