Ilya Palachev
Ilya Palachev

Reputation: 304

Monkey-patching class with inherited classes in Python

After reading the answers to the question about monkey-patching classes in Python I tried to apply the advised solution to the following case.

Imagine that we have a module a.py

class A(object):
    def foo(self):
        print(1)

class AA(A):
    pass

and let us try to monkey patch it as follows. It works when we monkey patch class A:

>>> import a
>>> class B(object):
...     def foo(self):
...             print(3)
... 
>>> a.A = B
>>> x = a.A()
>>> x.foo()
3

But if we try the inherited class, it turns to be not patched:

>>> y = a.AA()
>>> y.foo()
1

Is there any way to monkey patch the class with all its inherited classes?

EDIT

For now, the best solution for me is as follows:

>>> class AB(B, a.AA):
...     pass
... 
>>> a.AA = AB
>>> x = a.AA()
>>> x.foo()
3

Any complex structure of a.AA will be inherited and the only difference between AB and a.AA will be the foo() method. In this way, we don't modify any internal class attributes (like __base__ or __dict__). The only remaining drawback is that we need to do that for each of the inherited classes.

Is it the best way to do this?

Upvotes: 8

Views: 2409

Answers (1)

chepner
chepner

Reputation: 531125

You need to explicitly overwrite the tuple of base classes in a.AA, though I don't recommend modifying classes like this.

>>> import a
>>> class B:
...   def foo(self):
...     print(2)
...
>>> a.AA.__bases__ = (B,)
>>> a.AA().foo()
2

This will also be reflected in a.A.__subclasses__() (although I am not entirely sure as to how that works; the fact that it is a method suggests that it computes this somehow at runtime, rather than simply returning a value that was modified by the original definition of AA).

It appears that the bases classes in a class statement are simply remembered, rather than used, until some operation needs them (e.g. during attribute lookup). There may be some other subtle corner cases that aren't handled as smoothly: caveat programmator.

Upvotes: 5

Related Questions