标签: python-dataclasses

使用 python 数据类拥有属性 getters 而没有 setters 的 pythonic 方法是什么?

我遇到一种情况,我需要将变量 a、b 和 c 一起存储在数据类中,其中c = f(a,b)a、b 可以发生变化。c打印对象时,I 需要与 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
Run Code Online (Sandbox Code Playgroud)

但是,调用此结果会导致AttributeError: can't set attribute. 我怀疑代码试图将 c 设置为field(init=False),但失败了,因为 c 没有设置器。

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

  • 没有c在 init 中
    • 在 repr、字段等中不显示 c,这会导致进一步的问题
  • 有一个@c.setter什么都不做的
    • 这在技术上是可行的,但涉及编写看似没有任何作用的样板代码。
    • 拥有一个永远不会被我编写的任何代码显式调用但使程序中断被删除的函数感觉危险且不干净。
    • 我还希望程序崩溃,而不是如果有人尝试直接修改 c 则默默地不执行任何操作。
  • 如上所述,但如果调用者不是(尾注中的函数), sys._getframe().f_back.f_code则在 setter 中使用会引发错误__init__
    • 仅是 …

python python-dataclasses

2
推荐指数
1
解决办法
3321
查看次数

Why can't I override `to_dict` method of a `dataclass` object that uses `dataclasses_json`?

dataclasses_json is a library that provides JSON capabilities to python's data classes. I noticed that overriding to_dict method has no effect. Here's an example:

@dataclass_json
@dataclass
class Message2:
    message: str
    weight: int
    def to_dict(self, encode_json=False):
        print('Custom to_dict')
        ret = {'MESSAGE': self.message, 'WEIGHT': self.weight}
        return ret
m2 = Message2('m2', 2)
print(m2.to_dict())
Run Code Online (Sandbox Code Playgroud)

The code prints the following:

{'message': 'm2', 'weight': 2}

While I was expecting

Custom to_dict
{'MESSAGE': 'm2', 'WEIGHT': 2}
Run Code Online (Sandbox Code Playgroud)

If I remove the @dataclass_json line, I get the desired output. …

python python-decorators python-dataclasses

2
推荐指数
1
解决办法
5941
查看次数

将辅助变量传递给数据类 __init__ 而不分配它们

我有一个根级config类,我通过依赖注入在我的代码库中传递它。

问题是,我有这个数据类,需要此配置中的一些属性来world_coords计算__post_init__().

为了保持测试干净并避免其他测试导入问题(此处未讨论),我希望能够将配置直接传递给此对象,而不是从导入中读取这些值。然而,如果我将配置构建为参数,它就会成为数据类的一个属性,这是我试图避免的。实际上不需要RoadSegmentNode保留使用过的配置的引用。

这是该类的基本结构:

@dataclass(eq=True, frozen=True)  # make hashable
class RoadSegmentNode:

    tile_index: Tuple[int, int]  # (r, c)
    dir: Direction
    node_type: RoadNodeType
    world_coords: Tuple[int, int] = field(init=False)

    def __post_init__(self):

        # (Use config variables here, e.g. `config.TILE_WIDTH`, to calculate x and y)

        # Hack to get around frozen=True. We don't care that we're mutating
        # an "immutable" object on __init__().
        object.__setattr__(self, "world_coords", (x, y))
Run Code Online (Sandbox Code Playgroud)

这是我为了保持依赖注入模型而采取的权宜之计,以暂时解除我的测试障碍。请注意RoadSegmentNode现在有一堆仅用于初始化的新属性。这比保留对配置的引用要好一点,因为至少它们是明确的,但它仍然是一个相当糟糕的设计。

@dataclass(eq=True, frozen=True)  # make hashable
class RoadSegmentNode: …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-dataclasses

2
推荐指数
1
解决办法
1918
查看次数

在数据类中解压 kwargs

kwargs我可以在创建数据类对象时使用,没有问题:

@dataclass()
class Data:
    name: str =         'Unnamed'
    additional: int =   None
    things: int =       None

dic = {'additional': 123, 'things': 456}
res = Data(name='Somename', **dic)
Run Code Online (Sandbox Code Playgroud)
Output: Data(name='Somename', additional=123, things=456)
Run Code Online (Sandbox Code Playgroud)

kwargs但是,当数据类不属于调用参数时,我想将其解包:

@dataclass()
class Data:
    name: str =         'Unnamed'
    additional: int =   None
    things: int =       None

    def __post_init__(self):
        self(**dic) #unpack kwargs to fields

dic = {'additional': 123, 'things': 456}
res = Data(name='Somename')
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses

2
推荐指数
1
解决办法
4482
查看次数

在 Python 数据类中使用默认 uuid 值

如果我执行以下命令:

@dataclass
class Test:
    hi: Optional[str] = field(
        default_factory=lambda: str(uuid.uuid1()))

@dataclass
class Test2:
    hi: Optional[str] = str(uuid.uuid1())

if __name__ == "__main__":
    a = Test() # Test(hi='115a865c-33be-11eb-94a1-34c93db23648')
    b = Test() # Test(hi='115a865d-33be-11eb-8c6f-34c93db23648')
    c = Test2() # Test2(hi='10e44300-33be-11eb-85eb-34c93db23648')
    d = Test2() # Test2(hi='10e44300-33be-11eb-85eb-34c93db23648')
Run Code Online (Sandbox Code Playgroud)

为什么Test会为每个实例返回不同的 uuid,而Test2每次都会返回相同的 uuid?

另外,为什么default factory需要而不需要default

python python-dataclasses

2
推荐指数
1
解决办法
3980
查看次数

数据类对象属性别名

我正在做一个项目来了解有关使用 Python 的更多信息dataclasses。具体来说,我试图将 API 响应表示为一个dataclass对象。但是,由于 API 响应的结构,我遇到了一个问题。

以下是 API 的响应示例:

{
    "@identifier": "example",
    "@name": "John Doe",
}
Run Code Online (Sandbox Code Playgroud)

有些字段的名称中包含特殊字符。这意味着我无法直接映射 my 的属性dataclass,因为@属性名称中不允许使用特殊字符 ( SyntaxError)。

有没有办法为我的属性定义别名dataclass,以便我可以将 API 响应直接映射到dataclass对象?或者是否有必要先清理响应?

python python-dataclasses

2
推荐指数
1
解决办法
7822
查看次数

Python:如何键入提示数据类?

下面的代码有效,但我收到 PyCharm 的以下警告:

在“(...) -> Any”中找不到参考__annotations__

我想这是因为我正在使用Callable. 我没有找到类似的东西Dataclass。我应该使用哪种类型?

from __future__ import annotations
from dataclasses import dataclass
from typing import Callable

@dataclass
class Fruit:
  color: str
  taste: str

def get_cls() -> Callable:
  return Fruit

attrs = get_cls().__annotations__  # <- IDE warning
print(attrs)
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses python-typing

2
推荐指数
1
解决办法
4132
查看次数

为什么在将字符串字段添加到由 Enum 实例化的数据类时会出现 AttributeError?

我对这种行为感到困惑:我有一个冻结的数据类,其中只需要 10 个,所以我想将它们放入枚举中,并且成功了。后来,我意识到我希望能够为它们命名,突然间,枚举无法实例化数据类。

import enum
import dataclasses as dc

class Stats(int, enum.Enum):
    HP = 0
    STA = 1
    SPD = 2
    ATK = 3
    DEF = 4
    SPATK = 5
    SPDEF = 6

@dc.dataclass(frozen=True)
class Strand:
    keeps: tuple[Stats, ...]
    costs: int

class Strands(Strand, enum.Enum):
    VIT =   ((Stats.HP,),              1000)
    END =   ((Stats.STA,),             1000)
    LTH =   ((Stats.SPD,),             1000)
    AGG =   ((Stats.ATK,),             1000)
    HRD =   ((Stats.DEF,),             1000)
    GFT =   ((Stats.SPATK,),           1000)
    DOM =   ((Stats.SPDEF,),           1000)
    VIGOR = ((Stats.HP, Stats.STA),    5000)
    MIGHT = ((Stats.ATK, …
Run Code Online (Sandbox Code Playgroud)

python enums python-dataclasses python-3.10

2
推荐指数
1
解决办法
563
查看次数

具有随机属性值的数据类的构造函数

您好,有人可以解释一下这里发生的事情:我想用随机值实例化对象。

@dataclass
class Particle:
    pos = (random.randint(0, 800), random.randint(0, 800))

for _ in range(3):
    p = Particle()
    print(p.pos)

Run Code Online (Sandbox Code Playgroud)

印刷:

  • (123, 586)
  • (123, 586)
  • (123, 586)

预期的行为将是具有不同值的三个元组。这里发生了什么事??

(当我使用普通类时,它按预期工作)

python python-dataclasses

2
推荐指数
1
解决办法
475
查看次数

冻结对数据类意味着什么?

什么之间的区别@dataclass(frozen=True)@dataclass(frozen=False)?我什么时候应该使用哪个?

python decorator python-3.x python-dataclasses

1
推荐指数
1
解决办法
4460
查看次数