I need to define __setattr__ for assignment of fields without properties, but use the setter/getter functions for fields with a property defined

后端 未结 1 1908
长情又很酷
长情又很酷 2021-02-10 11:26

Defining __setattr__ overrides all setter methods / properties I define in a class. I want to use the defined setter methods in the property, if a property exists

相关标签:
1条回答
  • 2021-02-10 12:03

    You need to rewrite your __setattr__ function. As per the docs, new style classes should use baseclass.__setattr__(self, attr, value) instead of self.__dict__[attr] = value. The former will lookup any descriptors whereas the latter will assign directly to the dict.

    So rewrite your method as

    def __setattr__(self, name, value):
        object.__setattr__(self, name, value)
    

    or

    def __setattr__(self, name, value):
        super(Test, self).__setattr__(name, value)
    

    and you'll be fine. The code

    class Test(object):
        @property
        def gx(self):
            print "getting gx"
            return self.__dict__['gx']
    
        @gx.setter
        def gx(self, value):
            print "setting gx"
            self.__dict__['gx'] = value
    
        def __setattr__(self, attr, value):
            print "using setattr"            
            object.__setattr__(self, attr, value)
    
    t = Test()
    t.gx = 4
    t.dummy = 5
    print t.gx
    print t.dummy
    
    print dir(Test)
    

    outputs

    using setattr
    setting gx
    getting gx
    using setattr
    4
    5
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gx']
    

    I don't know why your version is calling the getter twice. This one doesn't. Also, to answer your question about where descriptors live, you can plainly see it as the last entry in the class dict.

    It's worth noting that you don't need __setattr__ to do what you want in your example. Python will always write an assignment foo.bar = x to foo.__dict__['bar'] = x regardless of if there's an entry in foo.__dict__ or not. __setattr__ is for when you want to transform the value or log the assignment or something like that.

    0 讨论(0)
提交回复
热议问题