網站首頁 編程語言 正文
前言:
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)
in ()
? ? ? 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__字典中。
原文鏈接:https://zhuanlan.zhihu.com/p/101004827
相關推薦
- 2022-09-05 UserWarning: indexing with dtype torch.uint8 is no
- 2022-02-27 Remove untracked files, stash or commit any change
- 2023-07-28 ElementUI el-tabs切換之前判斷是否滿足切換條件 不滿足條件僅提示不切換Tab
- 2022-01-30 Unknown custom element: <router-view> - did you re
- 2022-12-09 C++中使用cout以hex格式輸出方式_C 語言
- 2024-04-08 啟動spring-boot出現Error creating bean with name ‘conf
- 2022-07-06 C#多線程之線程池ThreadPool詳解_C#教程
- 2022-04-05 less calc計算有問題
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支