python中內(nèi)置類型添加屬性問(wèn)題詳解
python中內(nèi)置類型添加屬性問(wèn)題?
最近項(xiàng)目 進(jìn)行重構(gòu)一些代碼:
寫代碼過(guò)程中會(huì)遇到一個(gè)問(wèn)題,我希望通過(guò)內(nèi)置類型生成的對(duì)象 添加屬性,但是添加總是失敗.
obj = object() obj.name = 'frank'
報(bào)錯(cuò)如下:
Traceback (most recent call last):
File input, line 2, in
AttributeError: 'object' object has no attribute 'name'
普通對(duì)象綁定屬性
我們知道python 語(yǔ)言的動(dòng)態(tài)性, 是允許可以直接在是一個(gè)實(shí)例添加屬性的。
class Animal:
def eat(self):
pass
def sleep(self):
pass在python console 里面運(yùn)行,可以看到是可以正常添加屬性name
>>> animal = Animal() >>> animal.name='dog' >>> animal.name 'dog'
對(duì)比這兩個(gè)類的不同點(diǎn):
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
結(jié)果如下:
{'__module__', '__weakref__', '__dict__'}
################################################
set()
發(fā)現(xiàn)self 多了三個(gè)魔術(shù)方法。 我們來(lái)重點(diǎn)關(guān)注 __dict__ 方法,我們知道一個(gè)對(duì)象的屬性,一般放在 這個(gè)屬性上面的。 但是object 的實(shí)例 沒(méi)有這個(gè)屬性。
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__)結(jié)果如下:

在 animal 對(duì)象中, 屬性已經(jīng)存放在了 __dict__ 中。 而obj對(duì)象就沒(méi)有 __dict__ 這個(gè)屬性。
而我有一個(gè)大膽的想法,有沒(méi)有辦法可以直接在obj 實(shí)例上把 __dict__ 綁定到這個(gè)實(shí)例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__'
發(fā)現(xiàn)并不能綁定成功,python 里面不允許這樣綁定。
在python中 所有內(nèi)置對(duì)象 list,dict,set ,object 等等,這些內(nèi)置對(duì)象,不允許在里面添加 屬性,方法等。
這樣做是一個(gè)不好的行為,一旦你對(duì)內(nèi)置對(duì)象做了修改,其他引用內(nèi)置對(duì)象的代碼,是否會(huì)受到影響呢 ? 這是一個(gè)不可預(yù)期的行為。
解決方法
比較好的做法:想綁定一個(gè)屬性 在一個(gè)對(duì)象上面??梢宰远x一個(gè)類。然后綁定屬性,而不是在內(nèi)置類型生成的對(duì)象進(jìn)行綁定。
class Object(object):
pass
>>> obj = Object()
>>> obj.__dict__
{}
>>> obj.name='frank'
>>> obj.__dict__
{'name': 'frank'}
>>> obj.name
'frank'從網(wǎng)上找到一個(gè)解決方案在內(nèi)置類型上面可以添加方法 ,但是記得不要在生產(chǎn)環(huán)境這樣玩!
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)總結(jié)
不要在python內(nèi)置對(duì)象上面添加方法和屬性。因?yàn)檫@種行為是不可預(yù)期的,最好的做法繼承內(nèi)置對(duì)象,在派生子類中添加屬性,方法等。
到此這篇關(guān)于python中內(nèi)置類型添加屬性問(wèn)題詳解的文章就介紹到這了,更多相關(guān)python添加屬性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python編程中內(nèi)置的NotImplemented類型的用法
- Python語(yǔ)言內(nèi)置數(shù)據(jù)類型
- python入門課程第四講之內(nèi)置數(shù)據(jù)類型有哪些
- Python實(shí)現(xiàn)動(dòng)態(tài)給類和對(duì)象添加屬性和方法操作示例
- Python實(shí)現(xiàn)動(dòng)態(tài)添加屬性和方法操作示例
- Python Xml文件添加字節(jié)屬性的方法
- 在python的類中動(dòng)態(tài)添加屬性與生成對(duì)象
- Python實(shí)現(xiàn)動(dòng)態(tài)添加類的屬性或成員函數(shù)的解決方法
相關(guān)文章
pytorch自定義不可導(dǎo)激活函數(shù)的操作
這篇文章主要介紹了pytorch自定義不可導(dǎo)激活函數(shù)的操作,具有很好的參考價(jià)值,希望大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Python tkinter事件高級(jí)用法實(shí)例
這篇文章主要介紹了Python tkinter事件高級(jí)用法,結(jié)合實(shí)例形式分析了Python使用tkinter模塊的事件響應(yīng)及圖形繪制相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
Python爬蟲基礎(chǔ)之XPath語(yǔ)法與lxml庫(kù)的用法詳解
這篇文章主要給大家介紹了關(guān)于Python爬蟲基礎(chǔ)之XPath語(yǔ)法與lxml庫(kù)用法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09
Python將一個(gè)CSV文件里的數(shù)據(jù)追加到另一個(gè)CSV文件的方法
今天小編就為大家分享一篇Python將一個(gè)CSV文件里的數(shù)據(jù)追加到另一個(gè)CSV文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
Python中的Numpy?面向數(shù)組編程常見(jiàn)操作
這篇文章主要介紹了Python中的Numpy?面向數(shù)組編程常見(jiàn)操作,使用Numpy數(shù)組可以使你利用簡(jiǎn)單的數(shù)組表達(dá)式完成多項(xiàng)數(shù)據(jù)操作任務(wù),而不需要編寫大量的循環(huán),這個(gè)極大的幫助了我們高效的解決問(wèn)題2022-07-07

