簡體   English   中英

Python 名稱修改允許雙向訪問

[英]Python name mangling allows access both ways

所以我遇到了一個非常有趣的 python 名稱修改行為。 考慮以下代碼

class C:
    def __init__(self):
        self.__c = 1
    
    @staticmethod
    def change(instance):
        print(dir(instance))
        print(instance.__c)
        print(instance._C__c)

在這里,我創建了一個私有字段 __c 並希望可以從 class 內部直接訪問它,並從 class 外部通過 _C__c 訪問它。 因此,如果我們將 C 的實例傳遞給 C。更改第二次或第三次打印都應該失敗。
讓我們檢查:


>>> c =  C()
>>> dir(c)
['_C__c', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'change']
>>> C.change(c)
['_C__c', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'change']
1
1

首先,為了調試,我們使用dir(c)打印 c 的所有可用成員。 然后我們調用 C.change 傳遞變量c
嗯,這是意料之外的,沒有錯誤。
因此,第一個 print in change向我們展示了instance object 的所有可用條目。 在這里,我們看到字段__c可用作_C__c 這似乎沒問題,因為我們不是通過自我訪問,而是通過另一個變量。
從“dir”獲得這樣的 output 我希望print(instance.__c)會因 AttributeError 而失敗。
然而,出乎意料的是,它工作得很好!
這真的讓我很困惑,因為我不明白,為什么__c可以訪問,如果是這樣設計的,那么為什么它沒有在dir output 中列出?

每當您在 class 中寫入__c時,它將在文本上被_<classname>__c替換。 它不是動態執行的,它是在解析階段完成的。 因此,解釋器永遠不會看到__c ,只會看到_<classname>__c 這就是為什么只有_C__c出現在dir(instance)中。

引用文檔

[...] 在為其生成代碼之前,私有名稱會被轉換為更長的形式。 轉換插入 class 名稱,在名稱前面刪除了前導下划線並插入了一個下划線。 例如,出現在名為Ham的 class 中的標識符__spam將轉換為_Ham__spam 此轉換與使用標識符的語法上下文無關。 [...]

因此,它僅適用於點屬性訪問 ( xy ),不適用於通過(get|set)attr進行的動態訪問:

>>> class Foo:
...     def __init__(self):
...         setattr(self, '__x', 'test')
... 
>>> Foo().__x
'test'

__前綴名稱類自己的方法中可以正常工作。 由於name-mangling ,只有class (包括在其子類中)之外,才需要修改后的名稱才能訪問該屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM