首頁 > 軟體

python魔法方法之__setattr__()

2022-03-10 13:00:49

前言:

python提供了諸多的魔法方法,其中__setattr__()方法主要用於類範例進行屬性賦值,其定義在Object類官方提供的說明如下:

Called when an attribute assignment is attempted. 
This is called instead of the normal mechanism (i.e. store the value in the instance dictionary).
 name is the attribute name, value is the value to be assigned to it.

簡單的說,__setattr__()在屬性賦值時被呼叫,並且將值儲存到範例字典中,這個字典應該是self的__dict__屬性。即:在類範例的每個屬性進行賦值時,都會首先呼叫__setattr__()方法,並在__setattr__()方法中將屬性名和屬性值新增到類範例的__dict__屬性中。

1、範例屬性管理__dict__

下面的測試程式碼中定義了三個範例屬性,每個範例屬性註冊後都print()此時的__dict__

程式碼如下:

class AnotherFun:
    def __init__(self):
        self.name = "Liu"
        print(self.__dict__)
        self.age = 12
        print(self.__dict__)
        self.male = True
        print(self.__dict__)
another_fun = AnotherFun()

得到的結果顯示出,每次範例屬性賦值時,都會將屬性名和對應值儲存到__dict__字典中:

{'name': 'Liu'}
{'name': 'Liu', 'age': 12}
{'name': 'Liu', 'age': 12, 'male': True}

2、__setattr__()與__dict__

由於每次類範例進行屬性賦值時都會呼叫__setattr__(),所以可以過載__setattr__()方法,來動態的觀察每次範例屬性賦值時__dict__()的變化。下面的Fun類過載了__setattr__()方法,並且將範例的屬性和屬性值作為__dict__的鍵-值對:

class Fun:
    def __init__(self):
        self.name = "Liu"
        self.age = 12
        self.male = True
        
    def __setattr__(self, key, value):
        print("*"*50)
        print("setting:{},  with:{}".format(key[], value))
        print("current __dict__ : {}".format(self.__dict__))
        # 屬性註冊
        self.__dict__[key] = value
fun = Fun()    

通過在__setattr__()中將屬性名作為key,並將屬性值作為value,新增到了__dict__中,得到的結果如下:

**************************************************
setting:name,  with:Liu
current __dict__ : {}
**************************************************
setting:age,  with:12
current __dict__ : {'name': 'Liu'}
**************************************************
setting:male,  with:True
current __dict__ : {'name': 'Liu', 'age': 12}

可以看出,__init__()中三個屬性賦值時,每次都會呼叫一次__setattr__()函數。

3、過載__setattr__()必須謹慎

由於__setattr__()負責在__dict__中對屬性進行註冊,所以自己在過載時必須進行屬性註冊過程,下面是__setattr__()不進行屬性註冊的例子:

class NotFun:
    def __init__(self):
        self.name = "Liu"
        self.age = 12
        self.male = True
    
    def __setattr__(self, key, value):
        pass
not_fun = NotFun()
print(not_fun.name)

由於__setattr__中並沒有將屬性註冊到__dict__中,所以not_fun物件並沒有name屬性,因此最後的print(not_fun.name)會報出屬性不存在的錯誤:

AttributeError                            Traceback (most recent call last)
<ipython-input-21-6158d7aaef71> in <module>()
      8         pass
      9 not_fun = NotFun()
---> 10 print(not_fun.name)

AttributeError: 'NotFun' object has no attribute 'name'

所以,過載__setattr__時必須要考慮是否在__dict__中進行屬性註冊。

總結:

python的範例屬性的定義、獲取和管理可以通過__setattr__()和__dict__配合進行,當然還有對應的__getattr__()方法,本文暫時不做分析。__setattr__()方法在類的屬性賦值時被呼叫,並通常需要把屬性名和屬性值儲存到self的__dict__字典中。

到此這篇關於python魔法方法之__setattr__()的文章就介紹到這了,更多相關python魔法內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com