Based on my understanding of Python's data model, and specifically the subsection "Instance Methods", whenever you read an attribute whose value is of type "user-defined function", some magic kicks in and you get a bound instance method instead of the actual, original function. That magic is why you don't explicitly pass the self
parameter when you're calling a method.
But then, I would expect to be able to replace an object's method with a function with the same signature:
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)
I'm creating an instance of Scriptable
, and setting its script
attribute to a user-defined function with a single parameter, just like what's defined in the class. So when I read the scriptable.script
attribute, I would expect the magic to kick in and give me a bound instance method that takes no parameters (just like I get when I didn't replace script
). Instead, it seems to be giving back the exact same function I passed in, self
parameter and all. The method-binding magic isn't happening.
Why does the method-binding magic work when I define a method inside the class declaration, but not when I assign the attribute? What makes Python treat these situations differently?
I'm using Python3 if it makes any difference.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…