gpt4 book ai didi

python - 什么是使用 python 数据类在没有 setter 的情况下拥有属性 getter 的 pythonic 方法?

转载 作者:行者123 更新时间:2023-12-01 21:52:40 25 4
gpt4 key购买 nike

我遇到这样一种情况,我需要将变量 a、b 和 c 一起存储在一个数据类中,其中 c = f(a,b) 和 a,b 可以改变。我需要 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 没有 setter 。

我考虑过的选项(不包括我尝试过的导致代码以不同方式崩溃的替代方案):

  • 在初始化中没有c
    • 不在 repr、字段等中显示 c,这会导致进一步的问题
  • 有一个什么都不做的@c.setter
    • 这在技术上可行,但涉及编写看似什么都不做的样板代码。
    • 有一个函数永远不会被我编写的任何代码显式调用,但会使程序中断被删除,这让人感觉危险和不干净。
    • 我还希望程序崩溃,而不是在有人试图直接修改 c 时静静地什么都不做。
  • 如上,但如果调用者不是 __init__(尾注处的函数),则在 setter 中使用 sys._getframe().f_back.f_code 引发错误
    • 仅是 CPython 实现细节。
    • 一般来说,使用标记为私有(private)的函数不是一个好主意。
  • 让Demo不可变,在__post_init__中创建c,并使用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< 以外的东西.

关于python - 什么是使用 python 数据类在没有 setter 的情况下拥有属性 getter 的 pythonic 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58948671/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com