網站首頁 編程語言 正文
python中內置類型添加屬性問題?
最近項目 進行重構一些代碼:
寫代碼過程中會遇到一個問題,我希望通過內置類型生成的對象 添加屬性,但是添加總是失敗.
obj = object() obj.name = 'frank'
報錯如下:
Traceback (most recent call last):
File input, line 2, in
AttributeError: 'object' object has no attribute 'name'
普通對象綁定屬性
我們知道python 語言的動態性, 是允許可以直接在是一個實例添加屬性的。
class Animal: def eat(self): pass def sleep(self): pass
在python console 里面運行,可以看到是可以正常添加屬性name
>>> animal = Animal() >>> animal.name='dog' >>> animal.name 'dog'
對比這兩個類的不同點:
class Animal(object): def __init__(self): # print(sorted(dir(self))) res = set(dir(self)) - set(dir(object)) print(res) print('########' * 10) res = set(dir(object)) - set(dir(self)) print(res) pass
結果如下:
{'__module__', '__weakref__', '__dict__'}
################################################
set()
發現self
多了三個魔術方法。 我們來重點關注 __dict__
方法,我們知道一個對象的屬性,一般放在 這個屬性上面的。 但是object 的實例 沒有這個屬性。
def main(): obj = object() try: print(obj.__dict__) except AttributeError as e: print("ERROR:", e) animal = Animal() print(animal.__dict__, type(animal.__dict__)) animal.name = 'animal' animal.age = 10 print(animal.__dict__)
結果如下:
在 animal 對象中, 屬性已經存放在了 __dict__
中。 而obj對象就沒有 __dict__
這個屬性。
而我有一個大膽的想法,有沒有辦法可以直接在obj 實例上把 __dict__
綁定到這個實例obj 上面呢?
在python console 里面嘗試下:
>>> obj = object() >>> >>> obj.__dict__ = dict() Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'object' object has no attribute '__dict__' >>> setattr(obj,'__dict__',dict()) Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'object' object has no attribute '__dict__'
發現并不能綁定成功,python 里面不允許這樣綁定。
在python中 所有內置對象 list,dict,set ,object 等等,這些內置對象,不允許在里面添加 屬性,方法等。
這樣做是一個不好的行為,一旦你對內置對象做了修改,其他引用內置對象的代碼,是否會受到影響呢 ? 這是一個不可預期的行為。
解決方法
比較好的做法:想綁定一個屬性 在一個對象上面。可以自定義一個類。然后綁定屬性,而不是在內置類型生成的對象進行綁定。
class Object(object): pass >>> obj = Object() >>> obj.__dict__ {} >>> obj.name='frank' >>> obj.__dict__ {'name': 'frank'} >>> obj.name 'frank'
從網上找到一個解決方案在內置類型上面可以添加方法 ,但是記得不要在生產環境這樣玩!
import ctypes class PyObject(ctypes.Structure): class PyType(ctypes.Structure): pass ssize = ctypes.c_int64 if ctypes.sizeof(ctypes.c_void_p) == 8 else ctypes.c_int32 _fields_ = [ ('ob_refcnt', ssize), ('ob_type', ctypes.POINTER(PyType)), ] def sign(klass, func_name): def _(function): class SlotsProxy(PyObject): _fields_ = [('dict', ctypes.POINTER(PyObject))] name, target = klass.__name__, klass.__dict__ proxy_dict = SlotsProxy.from_address(id(target)) namespace = {} ctypes.pythonapi.PyDict_SetItem( ctypes.py_object(namespace), ctypes.py_object(name), proxy_dict.dict, ) namespace[name][func_name] = function return _ # method-1 @sign(list, 'mean') def mean(l): return sum(l) / len(l) # # @sign(list, 'max') def mean(l): return max(l) # method-2 sign(list, 'mean')(lambda l: sum(l) / len(l)
總結
不要在python內置對象上面添加方法和屬性。因為這種行為是不可預期的,最好的做法繼承內置對象,在派生子類中添加屬性,方法等。
原文鏈接:https://blog.csdn.net/u010339879/article/details/122788524
相關推薦
- 2022-10-15 Python?UnicodedecodeError編碼問題解決方法匯總_python
- 2022-02-05 lxml提取html標簽內容, tostring()不能顯示中文 解決方案
- 2022-05-21 Kubernetes特別屬性的標簽Label的強大作用_服務器其它
- 2022-02-03 ionic集成極光推送之點擊推送跳轉到指定頁面
- 2022-03-21 C++名稱空間介紹_C 語言
- 2022-07-29 python?判斷字符串當中是否包含字符(str.contain)_python
- 2022-07-02 C++精要分析右值引用與完美轉發的應用_C 語言
- 2024-03-21 解決SpringBoot項目中的報錯:Could not autowire,no beans of
- 最近更新
-
- 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同步修改后的遠程分支