Adding base class to existing object in python

后端 未结 3 1723
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-11 22:28

I have several objects of different kinds (different function names, different signatures) and I monkey patch them to have a common way to access them from different functio

相关标签:
3条回答
  • 2021-01-11 23:04

    To add a class to another classes bases, you could do something like this:

    def pacher_of_some_type(object):
    
        #this class holds all the stuff you want to add to the object
        class Patch():
            def target(self, value):
                #do something
    
        #add it to the class' base classes
        object.__class__.__bases__ += (Patch, )
    

    But this will affect ALL objects of this class as you actually change the class itself, which doesn't seem to be what you want... if you just want to patch an Instance, you could subclass the original class and change the instances class dynamically:

    class PatchedClass(object.__class__):
        def target(self, value):
            #do whatever
    
    object.__class__ = PatchedClass
    

    In terms of safety and manageability, I'd say dynamically adding a base class is as maintainable as dynamically adding some functions, and safer because you're less likely to accidentally overwrite some internal functions of the original class because the new base class is added to the end of the tuple, meaning it is used last for name resolution. If you actually want to overwrite methods, add them to the beginning of the base classes tuple (of course this doesn't apply to the subclass approach). Don't ask me if dynamically changing the class of an instance is safe at all, but in a trivial example it didn't seem to be a problem:

    class A():
        def p(self): print 1
    
    class B():
        def p(self): print 2
    
    a = A()
    a.p()    #prints 1
    a.__class__ = B
    a.p()    #prints 2
    
    0 讨论(0)
  • 2021-01-11 23:05

    Based on a comment on another answer, this is another way to patch the base class:

    class Patched(instance.__class__, ExtraBase):
        pass
    
    instance.__class__ = Patched
    
    0 讨论(0)
  • 2021-01-11 23:24

    Dynamically modifying an object's type is reasonably safe, as long as the extra base class is compatible (and you'll get an exception if it isn't). The simplest way to add a base class is with the 3-argument type constructor:

    cls = object.__class__
    object.__class__ = cls.__class__(cls.__name__ + "WithExtraBase", (cls, ExtraBase), {})
    
    0 讨论(0)
提交回复
热议问题