I am writing a python class that uses __setattr__ and __getattr__ to provide user access to attributes.
However, some attributes cannot be handled in a general way, so I was hoping to use descriptors for them.
The problem is that for the descriptor, the __get__ descriptor will be invoked in favor of __getattr__ instances, but when assigned to the __setattr__ attribute, __setattr__ will be invoked in favor of __set__ descriptors.
Example:
class MyDesc(object): def __init__(self): self.val = None def __get__(self, instance, owner): print "MyDesc.__get__" return self.val def __set__(self, instance, value): print "MyDesc.__set__" self.val = value class MyObj(object): foo = MyDesc() def __init__(self, bar): object.__setattr__(self, 'names', dict( bar=bar, )) object.__setattr__(self, 'new_names', dict()) def __setattr__(self, name, value): print "MyObj.__setattr__ for %s" % name self.new_names[name] = value def __getattr__(self, name): print "MyObj.__getattr__ for %s" % name if name in self.new_names: return self.new_names[name] if name in self.names: return self.names[name] raise AttributeError(name) if __name__ == "__main__": o = MyObj('bar-init') o.bar = 'baz' print o.bar o.foo = 'quux' print o.foo
prints:
MyObj.__setattr__ for bar MyObj.__getattr__ for bar baz MyObj.__setattr__ for foo MyDesc.__get__ None
The __set__ descriptor __set__ never called.
Since the definition of __setattr__ does not just redefine the behavior for a limited set of names, there is no clear place that can be delayed until object.__setattr__
Is there a recommended way to assign attributes to use a descriptor, if one is available, and __setattr__ otherwise?