Asignación de una función a un atributo de objeto

Basado en mi comprensión de Modelo de datos de Python, y específicamente la subsección "Métodos de instancia", cada vez que lee un atributo cuyo valor es del 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 original real. Esa magia es la razón por la que no pasas explícitamente laself parámetro cuando estás llamando a un método.

Pero entonces, esperaría poder reemplazar el 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 deScriptable, y estableciendo suscript atributo a una función definida por el usuario con un único parámetro, tal como se define en la clase. Entonces cuando leí elscriptable.script atributo, esperaría que la magia entrara en acción y me diera un método de instancia enlazado que no tome parámetros (al igual que cuando no reemplacéscript). En cambio, parece estar devolviendo exactamente la misma función que pasé,self parámetro y todo. La magia de vinculación de métodos no está sucediendo.

¿Por qué funciona la magia de enlace 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.

Respuestas a la pregunta(4)

Su respuesta a la pregunta