[英]`object.__setattr__(self, …, …)` instead of `setattr(self, …, …)`?
[英]python frozen dataclass immutable with object.__setattr__
在遇到數據類之前,我將 namedtuples 用於不可變數據結構,我在用例中更喜歡它(與問題無關)。
現在我了解到它們不是一成不變的。 至少嚴格來說不是。
setattr(frozen_dc_obj, "prop", "value")
引發異常。 行。
但為什么object.__setattr__(frozen_dc_obj,..)
有效?
與namedtuple
相比,它會引發異常!
from collections import namedtuple
from dataclasses import dataclass
NTTest = namedtuple("NTTest", "id")
nttest = NTTest(1)
setattr(nttest, "id", 2) # Exception
object.__setattr__(nttest, "id", 2) # Exception
@dataclass(frozen=True)
class DCTest:
id: int
dctest = DCTest(1)
setattr(dctest, "id", 2) # Exception
object.__setattr__(dctest, "id", 2) # WORKS
namedtuple定義了__slots__ = ()
因此你不能設置任何屬性(它沒有__dict__
)。
另一方面, 凍結數據類在其__setattr__
方法中執行手動檢查,如果它是凍結實例則引發異常。
比較以下內容:
>>> class Foo:
... __slots__ = ()
...
>>> f = Foo()
>>> f.__dict__ # doesn't exist, so object.__setattr__ won't work
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__dict__'
>>> @dataclass(frozen=True)
... class Bar:
... pass
...
>>> b = Bar()
>>> b.__dict__ # this exists, so object.__setattr__ works
{}
python Discord 頻道上的其他人給出了另一個很好的見解:
凍結的數據類可能通過其自己的 setattr 限制訪問,您可以通過將其傳遞給 object 來繞過它。
命名元組派生自實際的元組而不是 python 實現中的元組,因此它們可以是“真正的”不可變的,但是如果數據類要繞過接口(同樣可以以更混亂的方式對元組進行同樣的操作),這是一個有爭議的問題. 我建議在 namedtuple 上輸入 NamedTuple,因為它提供的可讀性是正確的 class,但是如果您需要數據類,那么凍結的數據類應該沒問題。 NamedTuple 並不是真正的類型提示,而是像數據類一樣在 class 定義中與它們一起工作,並為它提供比類類型構造函數更簡潔的定義。
我認為沒有辦法限制純 python 中的所有訪問,因為您可以調用對象的有效方法。
在元組上分配將涉及在 C 級別與 (c)python 交互,但在某種意義上它是相同的,因為它不是它的預期接口。
Python 總體而言,安全性並不大,如果不應該做某事,那么如果他們這樣做,那是用戶的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.