簡體   English   中英

python 凍結數據類與 object.__setattr__ 不可變

[英]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.

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