Consider the following code:
class Foo():
    pass
Foo.entries = dict()
a = Foo()
a.entries['1'] = 1
b = Foo()
b.entries['3'] = 3
print(a.entries)
This will print:
{'1': 1, '3': 3}
because the entries is added as static attribute. Is there a way monkey patch the class definition in order to add new attributes (without using inheritance).
I managed to find the following way but it looks convoluted to me:
def patch_me(target, field, value):
    def func(self):
        if not hasattr(self, '__' + field):
            setattr(self, '__' + field, value())
        return getattr(self, '__' + field)
    setattr(target, field, property(func))
patch_me(Foo, 'entries', dict)
                Ordinarily, attributes are added either by the __init__() function or after instantiating:
foo = Foo()
foo.bar = 'something'  # note case
If you want to do this automatically, inheritance is by far the simplest way to do so:
class Baz(Foo):
    def __init__(self):
        super().__init__()  # super() needs arguments in 2.x
        self.bar = 'something'
Note that classes don't need to appear at the top level of a Python module. You can declare a class inside a function:
def make_baz(value):
    class Baz(Foo):
        def __init__(self):
            super().__init__()  # super() needs arguments in 2.x
            self.bar = value()
    return Baz()
This example will create a new class every time make_baz() is called.  That may or may not be what you want.  It would probably be simpler to just do this:
def make_foo(value):
    result = Foo()
    result.bar = value()
    return result
If you're really set on monkey-patching the original class, the example code you provided is more or less the simplest way of doing it.  You might consider using decorator syntax for property(), but that's a minor change.  I should also note that it will not invoke double-underscore name mangling, which is probably a good thing because it means you cannot conflict with any names used by the class itself.
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