Why don't monkey-patched methods get passed a reference to the instance?
Asked Answered
P

2

11

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?

Pascia answered 15/4, 2014 at 2:36 Comment(0)
P
19

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
Prose answered 15/4, 2014 at 2:40 Comment(3)
Is this behavior limited to py3k?Johnsiejohnson
@BrianCain Nope. It is the same in Python 2.x alsoProse
Or use the function as a descriptor directly: sample.test = test.__get__(sample). Source link: func_descr_getBipack
B
2

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.

Bolin answered 15/4, 2014 at 2:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.