定制化属性访问###
getattribute(self, name): 被称作属性拦截器, 即所有对实例属性的访问都会先受到此方法的影响。此方法应该返回一个我们处理后的值,或者抛出一个AttributeError异常。 此方法应该谨慎使用。一般我们对个别属性做特殊处理后,都要加一个调用父类该方法,以免无限递归调用。
getattr(self, name): 当按照普通的属性访问方法访问不到一个属性时(即遇到AttributeError异常),此方法将被触发。这个方法也该要么返回一个处理后的值,要么抛出AttributeError异常。
setattr(self, name, value): 会拦截普通的属性赋值操作(也包括属性不存在时的创建并赋初值)。如果希望数据赋值给实例属性,则应该调用父类方法防止无限递归。
delattr(self, name): 当删除一个属性时,会触发此方法。比如 del obj.prop
使用上面这些方法,可以高度定制对属性的访问,修改,删除等操作。比如,可以控制不将属性存储在实例的__dict__
里,而是存储在某个指定的对象里。
class Foo():def __getattribute__(self, item):if item == 'prop1':return '被拦截了'else:# return self.item # 这种写法会造成无限递归return super().__getattribute__(item)def __getattr__(self, name):return '被__getattr_了'def __setattr__(self, key, value):if key == 'prop2':# self.prop2 = '被__setattr__了' # 这种写法会造成无限递归super().__setattr__(key, '被__setattr__了')else:super().__setattr__(key, value)foo = Foo()
foo.prop1 = 'prop1'
foo.prop2 = 'prop2'print('dir:', dir(foo))
print('vars:',vars(foo))
print('__dict__:',foo.__dict__)
print('foo.prop1:', foo.prop1)
print('foo.prop2:', foo.prop2)
print('foo.prop3:', foo.prop3)
返回结果:
dir: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'prop1', 'prop2']
vars: {'prop1': 'prop1', 'prop2': '被__setattr__了'}
__dict__: {'prop1': 'prop1', 'prop2': '被__setattr__了'}
foo.prop1: 被拦截了
foo.prop2: 被__setattr__了
foo.prop3: 被__getattr_了