1

I'd like to update some parent class in a python module to add a feature to all children classes. The module is installed via pip.

If I can modify the parent class, I just add methods to it. But, I should not edit installed modules. (following my previous discussion)

How can I add a feature to all children classes inside a python package without editing files inside pip package directories?

One alternative is using monkeypatching, but seems too tricky.

Update

Concrete situation is that I'd like to add common method to Child1 and Child2, but can not edit Parent because it is a class of a pip package.

class Parent:
    ...

class Child1(Parent):
    ...

class Child2(Parent):
    ...
Community
  • 1
  • 1
Light Yagmi
  • 5,085
  • 12
  • 43
  • 64

3 Answers3

0
class Parent:
    ...

class Mixin:
    def common_method (self, ...):
        ....

class Child1 (Parent, Mixin):
    ....

class Child2 (Parent, Mixin):
    ...

OR

class Parent:
    ...

class Augmented (Parent):
    def common_method (self, ...):
        ....

class Child1 (Augmented):
    ....

class Child2 (Augmented):
    ...
Jacques de Hooge
  • 6,750
  • 2
  • 28
  • 45
  • Sorry, I was ambiguous. Child1 and Child2 are also inside a `pip` package. So, I can not edit Child1 and Child2 – Light Yagmi Mar 10 '16 at 07:43
0

I'm not recommending this but you could use setattr

class Parent:
    age = 50

class Child(Parent):
    age = 20

def test(cls):
    print cls.age

setattr(Parent, 'some_func', classmethod(test))

Parent.some_func()
Child.some_func()

This outputs

50
20
quikst3r
  • 1,783
  • 1
  • 10
  • 15
  • 1
    This is monkey-patching and may be the best solution. There is no difference between `setattr(Parent, 'some_func', ...)` and `Parent.some_func = ...` that I'm aware of. – Jared Goguen Mar 17 '16 at 20:49
0

If the module doesn't rely on C code, I think monkey-patching may be the only solution short of enumerating the subclasses and manually adding the method to them.

test_module.py

class Parent(object):
    def __init__(self, name):
        self.name = name

class Child1(Parent): pass

class Child2(Parent): pass

other_file.py

from test_module import Parent, Child1, Child2

Parent.say = lambda self: self.name # monkey-patching

child1, child2 = Child1('Bob'), Child2('Larry')

print child1.say() # Bob
print child2.say() # Larry

You can even add the method to Parent after child1 and child2 are instantiated and still have access to it. This will also apply to new subclasses.

class Subchild(Child1): pass

Subchild('Moe').say() # Moe
Jared Goguen
  • 8,772
  • 2
  • 18
  • 36