__getattr__
拦截对象的点号运算。
当对为定义的属性名称和实例进行点号运算时,就会用属性名作为字符串调用这个方法。如果继承树可以找到该属性,则不调用此方法
class empty:
def __getattr__(self,attrname):
if attrname == 'age':
return 40
else:
return AttributeError,attrname
# `__getattr__`只有在使用点调用属性且属性不存在的时候才会触发
x = empyte()
print(x.age) #40
print(x.name) #报错
__serattr__
拦截所有属性的赋值语句。
如果定义了这个方法,self.attr = value 就会变为self.__setattr__('attr',value)
当在__setattr__方法内对属性进行赋值时,不可使用self.attr = value,因为他会再次
调用self.__setattr__('attr',value)
,则会形成无限递归,导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name']=value
class PrivateExc(Exception):
pass
class Privacy:
def __setattr__(self,attrname,value):
if attrname in self.privates:
raise PrivateExc(attrname,self)
else:
self.__dict__[attrname] = value
class Test1(privacy):
privates = ['age',]
class Test2(privacy):
pricates = ['name','age']
def __init__(self):
self.__dict__['name']='sun'
__delattr__
删除属性的时候触发
注意无限递归的问题,不要在__delattr__内部直接使用del删除属性
def __delattr__(self,item):
#del self.item 这样就无限递归了
self.__dict__.pop(item) #正确的方式