面向对象高级之 __getattr__,__setattr__,__delattr__

__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) #正确的方式

猜你喜欢

转载自www.cnblogs.com/guodengjian/p/9200685.html