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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章