[英]What is a pythonic way to have property getters without setters with python dataclasses?
我有一種情況,我需要將變量 a、b 和 c 一起存儲在一個數據類中,其中c = f(a,b)
和 a,b 可以突變。 打印 object 時,我需要c
與 a 和 b 一起顯示,並且c
不能更改,除非通過更改a
或b
。 我覺得做到這一點的最好方法是讓c
成為使用屬性創建的值。
我嘗試使用的最小示例:
@dataclass
class Demo:
a:int
b:int
c:int = field(init=False)
@property
def c(self) -> int:
return self.a * self.b
但是,調用它會導致AttributeError: can't set attribute
。 我懷疑代碼試圖將 c 設置為field(init=False)
,但由於 c 沒有設置器而失敗。
我考慮過的選項(不包括我嘗試過的使代碼以不同方式崩潰的替代方案):
c
@c.setter
__init__
(尾注中的函數),請在 setter 中使用sys._getframe().f_back.f_code
引發錯誤
c
中創建__post_init__
,並使用dataclasses.replace
修改 a 和 b。
Demo
的其他用途(嗯,實際的東西,而不是最小的例子)要求它是可變的。尾注:
@c.setter
def c(self, val):
caller = sys._getframe().f_back.f_code.co_name
if caller != '__init__':
raise ValueError # or some other error
如果您希望c
成為計算屬性,則完全取出c
字段並保留該屬性:
@dataclass
class Demo:
a:int
b:int
@property
def c(self) -> int:
return self.a * self.b
字段用於存儲數據, c
不應該是。
如果您希望c
出現在repr
中,您必須自己編寫__repr__
方法。 如果以后的代碼需要c
顯示在fields
中,那么您可能需要在更深層次上重新編寫代碼,並可能切換到dataclasses
以外的東西。
您的方法c
覆蓋您的字段c
- 原始field
聲明丟失,包括init=False
。
嘗試更改順序並使用default=
參數。
from dataclasses import dataclass, field
@dataclass
class Demo:
@property
def c(self) -> int:
return self.a * self.b
a: int
b: int
c: int = field(init=False, default=c)
d = Demo(5, 10)
print(d)
d.a = 10
print(d)
d.c = 4 # generates an AttributeError
Output 來自 Python 3.8.0:
Demo(a=5, b=10, c=50)
Demo(a=10, b=10, c=100)
Traceback (most recent call last):
...
File "/home/rob/src/plot/dc.py", line 20, in <module>
d.c = 4 # generates an AttributeError
AttributeError: can't set attribute
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.