Overriding __setattr__ at runtime

后端 未结 2 2037
自闭症患者
自闭症患者 2020-12-09 11:01

I am trying to override the __setattr__ method of a Python class, since I want to call another function each time an instance attribute changes its value. Howev

2条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-09 11:01

    @SingleNegationElimination's answer is great, but it cannot work with inheritence, since the child class's __mro__ store's the original class of super class. Inspired by his answer, with little change,

    The idea is simple, switch __setattr__ before __init__, and restore it back after __init__ completed.

    class CleanSetAttrMeta(type):
        def __call__(cls, *args, **kwargs):
            real_setattr = cls.__setattr__
            cls.__setattr__ = object.__setattr__
            self = super(CleanSetAttrMeta, cls).__call__(*args, **kwargs)
            cls.__setattr__ = real_setattr
            return self
    
    
    class Foo(object):
        __metaclass__ = CleanSetAttrMeta
    
        def __init__(self):
            super(Foo, self).__init__()
            self.a = 1
            self.b = 2
    
        def __setattr__(self, key, value):
            print 'after __init__', self.b
            super(Foo, self).__setattr__(key, value)
    
    
    class Bar(Foo):
        def __init__(self):
            super(Bar, self).__init__()
            self.c = 3
    
    >>> f = Foo()
    >>> f.a = 10
    after __init__ 2
    >>>
    >>> b = Bar()
    >>> b.c = 30
    after __init__ 2
    

提交回复
热议问题