Basado en mi comprensión de Python's data model, y específicamente en la subsección "Métodos de instancia", cada vez que lee un atributo cuyo valor es de tipo "función definida por el usuario", se activa algo mágico y se obtiene un método de instancia enlazado en lugar de la función real y original. Esa es la razón por la que no pasas explícitamente el parámetro self
cuando llamas a un método.Asignando una función a un atributo de objeto
Pero entonces, yo esperaría a ser capaz de sustituir al método de un objeto con una función con la misma firma:
class Scriptable:
def __init__(self, script = None):
if script is not None:
self.script = script # replace the method
def script(self):
print("greetings from the default script")
>>> scriptable = Scriptable()
>>> scriptable.script()
greetings from the default script
>>> def my_script(self):
... print("greetings from my custom script")
...
>>> scriptable = Scriptable(my_script)
>>> scriptable.script()
Traceback (most recent call last):
...
TypeError: script() takes exactly 1 positional argument (0 given)
estoy creando una instancia de Scriptable
, y el establecimiento de su atributo script
a un usuario función definida con un solo parámetro, tal como se define en la clase. Entonces, cuando leí el atributo scriptable.script
, esperaría que la magia entrara en acción y me diera un método de instancia enlazado que no tomara ningún parámetro (como lo hago cuando no reemplacé script
). En cambio, parece estar devolviendo exactamente la misma función que pasé, el parámetro self
y todo. La magia vinculante al método no está sucediendo.
¿Por qué funciona la magia de vinculación de métodos cuando defino un método dentro de la declaración de clase, pero no cuando asigno el atributo? ¿Qué hace que Python trate estas situaciones de manera diferente?
Estoy usando Python3 si hace alguna diferencia.
Al igual que con la mayoría de la magia, que fue diseñado para hacer exactamente lo que si me sale este derecho: "También es importante tener en cuenta que las funciones definidas por el usuario que son ** atributos de una instancia de clase ** son ** no ** convertidos a métodos enlazados, esto solo ocurre cuando la función es ** un atributo de la clase **. " Con la instrucción 'self.script' estás creando un atributo de instancia. El método estático 'Scriptable.script' todavía está allí. Una posible solución sería llamar a su 'script' inyectado en el antiguo método 'script'. –