Using both __setattr__ and descriptors for a python class
我正在编写一个python类,它使用
但是,有些属性不能用一般的方式处理,所以我希望对它们使用描述符。
出现了一个问题,对于描述符来说,描述符的
一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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 |
印刷品:
1 2 3 4 5 6 | MyObj.__setattr__ for bar MyObj.__getattr__ for bar baz MyObj.__setattr__ for foo MyDesc.__get__ None |
描述符的
由于
是否有一种建议的方法可以让分配给属性使用描述符(如果可用),否则使用
型
我想我会通过一种机制来自动标记每个类中的描述符,并用它调用的方式包装
这可以通过一个元类(和一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def setattr_deco(setattr_func): def setattr_wrapper(self, attr, value): if attr in self._descriptors: return object.__setattr__(self, attr, value) return setattr_func(self, attr, value) return setattr_wrapper class MiscSetattr(type): def __new__(metacls, name, bases, dct): descriptors = set() for key, obj in dct.items(): if key =="__setattr__": dct[key] = setattr_deco(obj) elif hasattr(obj,"__get__"): descriptors.add(key) dct["_descriptors"] = descriptors return type.__new__(metacls, name, bases, dct) # and use MiscSetattr as metaclass for your classes |
型
可能的方法之一:
1 2 3 4 5 6 7 | def __setattr__(self, name, value): print"MyObj.__setattr__ for %s" % name for cls in self.__class__.__mro__ + (self, ): if name in cls.__dict__: return object.__setattr__(self, name, value) print 'New name', name, value self.new_names[name] = value |
它检查名称是否已经在类、基类或实例中定义,然后调用
另一种方式:
1 2 3 4 5 6 7 8 9 | def __setattr__(self, name, value): print"MyObj.__setattr__ for %s" % name try: object.__getattribute__(self, name) except AttributeError: print 'New name', name, value self.new_names[name] = value else: object.__setattr__(self, name, value) |
号
但它将称为描述符的
附笔。
我不确定是否需要检查所有
也许