混合可变/不可变“数据容器”python

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

我想知道是否有一种方法可以在同一“数据容器”中定义可变/不可变/默认值的值。

“数据容器”是指诸如

tuple
dict
class
Enum
dataclass

之类的任何东西

这个例子让我的观点很清楚:

如果我想将

Page
first_page
current_page
last_page
作为值。

如果我使用

dataclass
方法,实现将是这样的:

from dataclasses import dataclass

@dataclass(slots=True)
class Pages:
    first_page: int = 0 # need to be immutable
    current_page: int   # need to be initialized and mutable
    last_page: int      # need to be initialized and immutable

这可以做到吗?或者有什么办法可以做到吗?

python immutability dataclasses
2个回答
0
投票

对于类,您可以使用 getter 和 setter。例如,要使

first_page
不可变,您可以创建一个名为
_first_page
的准私有属性(在 Python 中实际上不是私有的),您可以通过 (getter) 属性
first_page
属性访问该属性:

class Pages:
    _first_page: int = 0
    
    @property
    def first_page(self):
        return self._first_page

有了这个,你可以获得

first_page
,但是如果你尝试设置
first_page
,你会得到一个
AttributeError

p = Pages()
print(p.first_page)
0
p.first_page = 2
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[17], line 1
----> 1 p.first_page = 2

AttributeError: can't set attribute

您可以有一个等效的

setter
属性,它显式返回一条消息,表明
first_page
是不可变的并且不执行任何操作,例如:

class Pages:
    _first_page: int = 0
    
    @property
    def first_page(self):
        return self._first_page

    @first_page.setter
    def first_page(self, _):
        print("first_pass is immutable")
        pass

对于您想要可变的值,您可以像平常一样设置类属性,或者(如上所述)使用

@property
@setter
修饰函数来设置等效的准私有属性。


0
投票

您可以使用

field
中的
dataclasses

@dataclass(frozen=True)  # Making the dataclass frozen makes its fields immutable.
class Pages:
    _last_page: int = field(repr=False)  # Private field, and won't be shown in repr.
    _first_page: int = field(default=0, repr=False)
    current_page: int = field(default_factory=int, hash=False)  # Making it mutable by setting hash to False.

    @property
    def first_page(self) -> int:  # Property for the first_page to allow only reading.
        return self._first_page

    @property
    def last_page(self) -> int:  # Property for the last_page to allow only reading.
        return self._last_page

测试

p = Pages(current_page=5, _last_page=10)
print(p.first_page)  # 0
print(p.current_page)  # 5
print(p.last_page)  # 10

# This will raise an exception: dataclasses.FrozenInstanceError
# p.first_page = 2

frozen=True
确保属性保持不可变,除非另有指定。

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