摘要:?jiǎn)栴}起源在中對(duì)于某些屬性是只讀的,比如對(duì)于。這會(huì)導(dǎo)致一些令人費(fèi)解的錯(cuò)誤。首先,和是不同的,不存在,是指的實(shí)例擁有的屬性,它是一個(gè)描述器,調(diào)用它會(huì)返回實(shí)例的屬性。的調(diào)用會(huì)按照以下順序會(huì)按照同樣順序,但是很明顯會(huì)跳過的訪問。
0x01 Q-1: why types (str, int, dict, ...) __dict__ attribute is dict_proxy object in python2 (or mappingproxy object in python3.3+) ?
>>> str.__dict__ dict_proxy({"__add__":問題起源, "__contains__": , ..... "zfill": }) >>> type(str.__dict__) >>> s = "abc" >>> s.__dict__ Traceback (most recent call last): File " ", line 1, in AttributeError: "str" object has no attribute "__dict__"
在 Python 中對(duì)于某些 object __dict__ 屬性是只讀的,比如對(duì)于 type object。然而,在 Python2.5-2.6 之前,還是有一些一般性方法可以獲取和改變 __dict__ 屬性的(without hacking with
gc.get_referrents(), that is)。這會(huì)導(dǎo)致一些令人費(fèi)解的錯(cuò)誤。
dictproxy 是為了用于保證 class.__dict__ 的 keys 必須是 strings, proxy 的機(jī)制防止了對(duì)于 class.__dict__ 的寫入操作, 因此只有 setattr() 可以被用于添加屬性, class.__setattr__ 的實(shí)現(xiàn)確保了 keys-must-be-strings 的限制.
如果我們不使用一些 proxy 的機(jī)制,那么 __dict__,class.__dict__ 就可以被寫入了。如果可以寫入,也就可以被刪除,而 class.__dict__ 中的屬性被刪除可能會(huì)導(dǎo)致解釋器崩潰。
The __dict__ attribute of some objects is read-only,
e.g. for type objects. However, there is a generic
way to still access and modify it (without hacking with
gc.get_referrents(), that is). This can lead to
obscure crashes. Attached is an example that shows
a potential "problem" involving putting strange keys
in the __dict__ of a type.
This is probably very minor anyway. If we wanted to
fix this, we would need a __dict__ descriptor that
looks more cleverly at the object to which it is
applied.
BTW the first person who understand why the attached
program crashes gets a free coffee.
Q-2: why built-in class instances don"t have __dict__ attribute ?------- [Armin Rigo] Bypassing dict readonlyness [Python2.5-2.6]
Instances of types defined in C don"t have a __dict__ attribute by default.
Q-3: what is the __dict__["__dict__"] attribute of a Python class?>>> class A(object): x = "1" def __init__(self): self.x = "2" >>> a = A() >>> a.__dict__ {"x": "2"} >>> type(a.__dict__) dict >>> A.__dict__ dict_proxy({"__dict__":, "__doc__": None, "__init__": , "__module__": "__main__", "__weakref__": , "x": "1"}) >>> type(A.__dict__) dict_proxy >>> A.__dict__["__dict__"] >>> type(A.__dict__["__dict__"]) getset_descriptor >>> isinstance(A.__dict__["__dict__"], types.GetSetDescriptorType) True >>> A.__dict__["__dict__"].__get__(a, A) {"x": "2"} >>> a.__dict__ {"x": "2"}
首先,A.__dict__.__dict__ 和 A.__dict__["__dict__"] 是不同的,A.__dict__.__dict__ 不存在,A.__dict__["__dict__"] 是指 class 的實(shí)例擁有的 __dict__ 屬性,它是一個(gè)描述器,調(diào)用它會(huì)返回實(shí)例的 __dict__ 屬性。簡(jiǎn)單來說,因?yàn)橐粋€(gè)實(shí)例的 __dict__ 屬性不能(why?)保存在實(shí)例的 __dict__ 中,所以需要通過 class 中的一個(gè) descriptor 來調(diào)用。(因?yàn)?python 是動(dòng)態(tài)語(yǔ)言嘛,A.__dict__["__dict__"] 是一個(gè) GetsetDescriptor,所以實(shí)例的屬性是有能力增加的)
對(duì)于 class A 的實(shí)例 a ,訪問 a.__dict__ 時(shí)的背后是通過 A.__dict__["__dict__"] 實(shí)現(xiàn)的(vars(A)["__dict__"])
對(duì)于 class A,訪問 A.__dict__ 理論上 是通過 type.__dict__["__dict__"] 實(shí)現(xiàn)的(vars(type)["__dict__"])
完整解釋:
class 和實(shí)例訪問屬性都是通過屬性操作符 (class or metaclass"s __getattribute__) 和 __dict__ 屬性/協(xié)議實(shí)現(xiàn)的。
對(duì)于一般的實(shí)例對(duì)象,__dict__ 會(huì)返回一個(gè)保存包含所有實(shí)例屬性的獨(dú)立的 dict 實(shí)例對(duì)象,對(duì) __getattribute__ 的調(diào)用首先會(huì)訪問這個(gè) dict,并獲取相應(yīng)的實(shí)例屬性 (這個(gè)調(diào)用會(huì)在通過描述器協(xié)議訪問 class 屬性之前,也會(huì)在調(diào)用 __getattr__ 之前)。class 里定義的 __dict__ 描述器實(shí)現(xiàn)了對(duì)這個(gè) dict 的訪問。
x.name 的調(diào)用會(huì)按照以下順序: x.__dict__["name"], type(x).name.__get__(x, type(x)), type(x).name
x.__dict__ 會(huì)按照同樣順序,但是很明顯會(huì)跳過 x.__dict__["name"] 的訪問。
因?yàn)?x.__dict__ 不能保存在 x.__dict__["__dict__"] 中,對(duì)于 x.__dict__ 的訪問就會(huì)用描述器協(xié)議實(shí)現(xiàn),x.__dict__ 的值就會(huì)保存在實(shí)例中的一個(gè)特殊字段里。
對(duì)于 class 也會(huì)面臨相同的情況,雖然 class.__dict__ 是一個(gè)偽裝成 dict 的特殊的 proxy 對(duì)象,class.__dict__ 也不允許你對(duì)它進(jìn)行
修改或替換行為。這個(gè)特殊的 proxy 對(duì)象允許你,獲取那些定義在 class 而不是 class 的基類中的的屬性。
默認(rèn)情況下,vars(cls) 對(duì)于一個(gè)空類型,返回的對(duì)象包含三個(gè)描述器,__dict__ 用于保存實(shí)例中的屬性,__weakref__ 是用于 weakref 模塊的內(nèi)部邏輯,__doc__ 是用于 class 的 docstring。前兩個(gè)描述器可能會(huì)因?yàn)槎x了 __slots__ 而消失,沒有 __dict__ and __weakref__ 屬性,反而會(huì)有每一個(gè)定義在 __slots__ 的屬性。此時(shí),實(shí)例的屬性不會(huì)保存在 dict 中,訪問屬性將會(huì)通過相應(yīng)的描述器實(shí)現(xiàn)。
refs: What is the dict__.__dict attribute of a Python class?
Q-4: what"s the order of access instance"s attribute ?# -*- encoding: utf -*- class RevealAccess(object): """A data descriptor that sets and returns values normally and prints a message logging their access. """ def __init__(self, initval=None, name="var"): self.val = initval self.name = name def __get__(self, obj, objtype): print("Retrieving", self.name, self.val) return self.val def __set__(self, obj, val): print("Updating", self.name, self.val) self.val = val class Base(object): attr_1 = RevealAccess(10, "var "x"") def __init__(self): self.attr_2 = RevealAccess(10, "var "x"") def __getattribute__(self, *args, **kwargs): print("__getattribute__", args, kwargs) return super(Base, self).__getattribute__(*args, **kwargs) def __getattr__(self, *args, **kwargs): print("__getattr__", args, kwargs) try: origin = super(Base, self).__getattr__(*args, **kwargs) return origin except AttributeError as e: return "not found" def main(): b = Base() print("*********** start get b.attr_1 ***********") print(b.attr_1) print("*********** start get b.attr_2 ***********") print(b.attr_2) print("*********** start get b.attr_3 ***********") print(b.attr_3) if __name__ == "__main__": main() Output: *********** start get b.attr_1 *********** ("__getattribute__", ("attr_1",), {}) ("Retrieving", "var "x"", 10) 10 *********** start get b.attr_2 *********** ("__getattribute__", ("attr_2",), {}) <__main__.RevealAccess object at 0x100b1abd0> *********** start get b.attr_3 *********** ("__getattribute__", ("attr_3",), {}) ("__getattr__", ("attr_3",), {}) not found
Refs:
How Does Attribute Access Work?
Python: Difference between class and instance attributes
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/40676.html
摘要:溫習(xí)統(tǒng)計(jì)學(xué)的知識(shí)為更深層次的學(xué)習(xí)做準(zhǔn)備在的演講中說就是我們理解但不知道另外的是如何的我在臺(tái)下想對(duì)于那可以理解的我好像都只懂了參考標(biāo)準(zhǔn)高效的流程課程用的是我不想再學(xué)一門類似的語(yǔ)言了我會(huì)找出相對(duì)應(yīng)的和的來源流程什么是干凈的一個(gè)變 Why The Data Science Specialization 溫習(xí)統(tǒng)計(jì)學(xué)的知識(shí), 為更深層次的學(xué)習(xí)做準(zhǔn)備 Andrew Ng 在 2015 GTC ...
摘要:機(jī)器學(xué)習(xí)深度學(xué)習(xí)與自然語(yǔ)言處理領(lǐng)域推薦的書籍列表人工智能深度學(xué)習(xí)與相關(guān)書籍課程示例列表是筆者系列的一部分對(duì)于其他的資料集錦模型開源工具與框架請(qǐng)參考。 showImg(https://segmentfault.com/img/remote/1460000014946199); DataScienceAI Book Links | 機(jī)器學(xué)習(xí)、深度學(xué)習(xí)與自然語(yǔ)言處理領(lǐng)域推薦的書籍列表 sho...
閱讀 813·2021-11-18 10:02
閱讀 2503·2021-11-11 16:54
閱讀 2750·2021-09-02 09:45
閱讀 654·2019-08-30 12:52
閱讀 2774·2019-08-29 14:04
閱讀 2745·2019-08-29 12:39
閱讀 448·2019-08-29 12:27
閱讀 1887·2019-08-26 13:23