python冻结的数据类与对象不可变__

2024-09-30 02:27:10 发布

您现在位置:Python中文网/ 问答频道 /正文

在遇到数据类之前,我一直使用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


Tags: 数据fromimportidobjobjectexceptiondc
2条回答

python Discord频道上的其他人给出了另一个伟大的见解:

冻结的数据类可能通过其自身的setattr限制访问,您可以通过将其传递给对象来绕过setattr

命名元组是从实际元组而不是python中的实现派生的,因此它们可以“真正”不可变,但是如果您在接口中使用数据类(同样可以以更混乱的方式对元组进行处理),这是一个没有意义的点。 我建议使用NamedTuple,而不是在NamedTuple上键入,因为它提供了作为一个适当类的可读性,但是如果您需要dataclass,那么冻结的类就可以了。NamedTuple实际上不是一个typehint,但在类定义中与它们一起工作,就像dataclasses一样,与类构造函数相比,它的定义更简洁

我认为在纯python中并没有限制所有访问的方法,因为您可以调用对象的方法

在元组上赋值将涉及到在c级别与(c)python交互,但这在某种意义上是相同的,因为它不是它的预期接口

Python总体上不太重视安全性,如果不应该做一些事情,那么如果用户做了,那就是用户的问题

namedtuple定义了^{},因此您不能设置任何属性(它没有__dict__

Frozen dataclasses另一方面,在^{}方法中执行手动检查,如果是冻结的实例,则引发异常

比较以下各项:

>>> 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
{}

相关问题 更多 >

    热门问题