python魔法方法(三)__getattr__、__setattr__、__delattr__

1、getattr

当我们访问一个不存在的属性时,会抛出异常,提示不存在这个属性,而这个异常就是__getattr__方法抛出的,其原因在于他是访问一个不存在的属性的最后落脚点,作为异常抛出的地方提示出错再适合不过了。
举例:

class A(object):
    def __init__(self, value):
        self.value = value

    def __getattr__(self, item):
        print ("into __getattr__")
        return "can not find"

a = A(10)
print (a.value)
#10
print(a.name)
#into __getattr__
#can not find

可以看出,当访问存在的属性时,会正常返回,若该访问不存在,则返回__getattr__函数
源码:

def __getattr__(self, name):
	return getattr(caches[DEFAULT_CACHE_ALIAS], name)

-->getattr
def getattr(object, name, default=None):
	"""
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    getattr(object,name [,default])-> value从对象获取命名属性; getattr(x,'y')等效于xy给定默认参数时,如果该属性不提供则返回不		    存在;没有它,在这种情况下会引发异常。
    """
	pass

2、setattr

在对一个属性设置值的时候,会调用到这个函数,每个设置值的方式都会进入这个方法。

class A(object):
    def __init__(self, value):
        print("into __init__")
        self.value = value

    def __setattr__(self, name, value):
        print("into __setattr")
        if value == 10:
            print("from __init__")
        object.__setattr__(self, name, value)

a = A(10)
print(a.value)
'''
into __init__
into __setattr
from __init__
10
'''

在实例化的时候,会进行初始化,在__init__里,对value的属性值进行了设置,这时候会调用__setattr__方法。

需要注意的地方是,在重写__setattr__方法的时候千万不要重复调用造成死循环。
例如:

class A(object):
    def __init__(self, value):
        self.value = value
 
    def __setattr__(self, name, value):
        self.name = value

a = A(10)
print(a.value)
'''
  [Previous line repeated 328 more times]
RecursionError: maximum recursion depth exceeded
显示递归超出限制
'''

除了上面调用object类的__setattr__避开死循环,还可以如下重写__setattr__避开循环。
解决方法:

class A(object):
    def __init__(self, value):
        self.value = value
 
    def __setattr__(self, name, value):
        self.__dict__[name] = value
 
 
a = A(10)
print a.value
# 10

3、delattr

__delattr__是个删除属性的方法.

class A(object):
    def __init__(self, value):
        self.value = value
 
    def __delattr__(self, item):
        object.__delattr__(self, item)
 
    def __getattr__(self, item):
        return ("when can not find attribute into __getattr__")
 
a = A(10)
print(a.value)
# 10
del(a.value)
print(a.value)
# when can not find attribute into __getattr__

delattr__也要避免死循环的问题,就如__setattr__一样,在重写__delattr,避免重复调用。
源码:

def __delattr__(self, name):
    return delattr(caches[DEFAULT_CACHE_ALIAS], name)
    --->delattr
def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.
    delattr(x, 'y') is equivalent to ``del x.y''
    从给定对象中删除命名属性。 delattr(x,'y')等效于``del x.y''
    """
    pass
原创文章 35 获赞 13 访问量 2350

猜你喜欢

转载自blog.csdn.net/Bankofli/article/details/105081839