See this example for a demonstration:
>>> class M:
def __init__(self): self.x = 4
>>> sample = M()
>>> def test(self):
print(self.x)
>>> sample.test = test
>>> sample.test()
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
sample.test()
TypeError: test() missing 1 required positional argument: 'self'
Why?
The test
method you are assigning to sample.test
is not bound to the sample
object. You need to manually bind it like this
import types
sample.test = types.MethodType(test, sample)
sample.test()
# 4
Functions are objects like any other and there needs to be consistency on what happens when objects are assigned to names, regardless of where the names are (i.e. in local namespace or on as attributes on an object).
When you define a function with def
you are binding a function to the name after def
, and when you do assignment like some_object.f = my_function
you are also binding the function to a name. There's no magic in the assignment process that would change the nature of the function.
There is magic in the class definition process. Functions defined as instance methods (that is, functions defined inside a class definition) are not simply assigned as attributes to instances, but instead they are bound to the instance using a descriptor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With