我想知道是否有一种方法可以在同一“数据容器”中定义可变/不可变/默认值的值。
“数据容器”是指诸如
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
这可以做到吗?或者有什么办法可以做到吗?
对于类,您可以使用 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
修饰函数来设置等效的准私有属性。
您可以使用
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
确保属性保持不可变,除非另有指定。