python 修改冻结数据类

问题描述 投票:0回答:1

我有一个 python 数据类,我不打算修改其属性。 然而,正如我刚刚意识到的,当我设置

__dict__
时,它仍然可以通过 frozen=True
even
进行修改。例如:

@dataclass(frozen=True)
class C:
    a: int = 1

c = C()
c.a = 2 # dataclasses.FrozenInstanceError: cannot assign to field 'a'
c.__dict__['a'] = 2 # legit

print(c) 
# C(a=2)

我知道这是属于底层的

__dict__
attr 是一个可变对象,并且在
__setattr__
处引发错误并不能真正涵盖。

另一方面,我确实需要以集体方式访问所有属性。此类任务的最佳实践是什么?我要复印

__dict__
吗?或者也许
slots=True
会是一个潜在的候选人?

提前致谢。

python python-dataclasses readonly-attribute
1个回答
2
投票

正如您所意识到的,人们必须“好”地不遗余力地修改这些属性之一。 虽然可能比直接访问实例的

__dict__

来修改属性要困难一些,但由于 Python 的动态和自反性质,人们“总是”可以更改 Python 中的底层属性。语言。该语言的真正目的并不是阻止“想要”更改属性的人修改它(请注意,像 C++ 和 Java 这样的语言中的“私有”和“受保护”属性也可以通过以下方式更改:打算通过使用自反 API 或通过名称修改来做到这一点)。

换句话说,在一个“严重”的系统中,通过访问系统代码或类来修改属性的情况不应该是“危险的”,并且对于编写将在同一进程中运行的代码的开发人员来说应该是“危险的”。如果你有这样的设计思维,你最好重新考虑一下,更有可能将“只读”数据放在一个单独的服务中,通过 API 或其他 RPC 方法访问,这样潜在的“恶意编码者”就不会在进程中 访问您的变量。
总而言之,有一些方法可以冻结属性,这可能会阻止 __dict__

方法 - 其中之一是创建一个特殊的描述符,在实例上进行特定更改后将锁定写入:分配给描述符的属性课程不会通过

__dict__。但如上所述,任何想要更改属性的人都可以转到描述符保存属性的任何存储(它必须位于某个位置),或者简单地反转指示该值应该是只读的更改某个点。 我尝试了一下,并为这样的描述符想出了示例代码,但它真的非常愚蠢 - 因为它在某些时候必须使用“规避自身的方法”才能将类标记为锁定。但是,如您所描述的那样使用 __slots__

将适用于冻结的数据类,并且不会具有可变的

__dict__

 - 另一方面,通过类属性的 
.__set__
 方法来更改实例属性仍然很简单:
In [124]: @dataclass(frozen=True) ...: class A: ...: __slots__=("a",) ...: a: int ...: In [125]: a = A(42) In [126]: a.a = 23 FrozenInstanceError ... In [127]: a.__dict__ ... AttributeError: 'A' object has no attribute '__dict__' In [128]: A.a.__set__(a, 23) In [139]: a.a Out[139]: 23

© www.soinside.com 2019 - 2024. All rights reserved.