标签: python-dataclasses

如何比较具有相同继承的@dataclass的实例子类

我试图比较从公共基类(也是@dataclass)继承的两个数据类。

继承类的字段是它们特有的,在比较时不考虑;我只想比较基类属性。

这是我的尝试:

from dataclasses import dataclass, field

@dataclass(order=True)
class Base:
    a: float

@dataclass(order=True)
class ChildA(Base):
    attribute_a: str = field(compare=False)

@dataclass(order=True)
class ChildB(Base):
    attribute_b: str = field(compare=False)


ca = ChildA(1, 'a')
cb = ChildB(2, 'b')
ca < cb
Run Code Online (Sandbox Code Playgroud)

但是,我得到:

TypeError: '<' not supported between instances of 'ChildA' and 'ChildB'
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?

python python-3.x python-dataclasses

5
推荐指数
2
解决办法
2万
查看次数

在 __post_init__ 中设置可选数据类参数时如何避免检查 None

考虑一个参数具有可变默认值的数据类。为了能够使用新的默认值实例化一个对象而不是共享可变对象,我们可以这样做:

@dataclass
class ClassWithState:
    name: str
    items: Optional[List[str]] = None

    def __post_init__(self) -> None:
        if self.items is None:
            self.items = []
Run Code Online (Sandbox Code Playgroud)

这按预期工作。items然而,每当我在此类的某些实例中引用时,mypy 都会警告该items值可能为 None。例如:

c = ClassWithState("object name")
c.items.append("item1")
Run Code Online (Sandbox Code Playgroud)

MyPy 会抱怨类似以下内容:

“Optional[List[str]]”的项目“None”没有属性“append”。

我不想每次提到时都添加不必要的检查,items例如

assert c.items is not None
Run Code Online (Sandbox Code Playgroud)

我提到的到处都是items。我怎样才能说服mypyitems永远不会是None?

type-hinting python-3.x mypy python-dataclasses

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

数据类的post_init方法中定义的变量可以序列化吗?

from dataclasses import dataclass
@dataclass
class A:
    x: str
    y: str
    def __post_init__(self):
        self.z = self.x+self.y
Run Code Online (Sandbox Code Playgroud)
a = A('abc', 'def')
a.z
'abcdef'
from dataclasses import asdict
asdict(a)
{'x': 'abc', 'y': 'def'}
Run Code Online (Sandbox Code Playgroud)

可以看出,z并没有被序列化。如何序列化它(除了调用__dict__它之外)?

python python-dataclasses

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

Python:数据类的唯一整数?

我有以下数据类。

@dataclass(frozen=True)
class myDataClass:
    x: float
    y: float
Run Code Online (Sandbox Code Playgroud)

我想要的是,每次创建此类的对象时,它都会被标记一个从 0 开始递增的唯一 id。

所以,第一次我说first = myDataClass(0, 1)那么我应该得到first.id == 0,然后如果我说second = myDataClass(0, 1),我应该得到second.id == 1

python python-dataclasses

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

如何在序列化为 pandas 数据帧时展平嵌套数据类?

我有包含其他数据类作为其字段的数据类:

@dataclass
class Bar:
    abc: int
    bed: int
    asd: int


@dataclass
class Foo:
    xy: int
    yz: Bar
Run Code Online (Sandbox Code Playgroud)

然后我尝试通过 pandas 将其序列化为 csv,如下所示:

dataset = [Foo(xy=1, yz=Bar(abc=1, bed=2, asd=3))]
pd_dataset = pandas.DataFrame(vars(row) for row in dataset)
pd_dataset.to_csv('dataset_example.csv', index=False)
Run Code Online (Sandbox Code Playgroud)

但我得到的结果与我想要的有点不同。准确地说,我现在得到:

xy,yz
1,"Bar(abc=1, bed=2, asd=3)"
Run Code Online (Sandbox Code Playgroud)

而且我要:

xy,yz_abc,yz_bed,yz_asd
1,1,2,3
Run Code Online (Sandbox Code Playgroud)

你能帮我做对吗?我尝试编写自己的序列化函数并执行类似的操作: pandas.DataFrame(asdict(row, dict_factory=row_to_dict) for row in dataset) 但我不知道如何正确编写它。

python pandas python-dataclasses

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

组合@dataclass和@property

我想使用 @dataclass 来删除很多样板,但我也喜欢 @property 提供的数据封装。我可以同时做这两件事吗?

作为一个玩具示例,我有一个类似的课程

class Breakfast:

    def __init__(self, sausage: str, eggs: str = "Scrambled", coffee: bool = False):
        self._sausage = sausage
        self._eggs = eggs
        self._coffee = coffee

    @property
    def sausage(self):
        return self._sausage

    @property
    def eggs(self):
        return self._eggs

    @property
    def coffee(self):
        return self._coffee

    def __repr__(self):
        ...

    def __eq__(self):
        ...
Run Code Online (Sandbox Code Playgroud)

我可能还为某些属性设置了设置器。我想要的是以这样的形式写这个

@dataclass(property=True)
class DataBreakfast:
    sausage: str
    eggs: str = "Scrambled"
    coffee: bool = False
Run Code Online (Sandbox Code Playgroud)

(当然,我的装饰器参数不起作用)它将执行 @dataclass 所做的所有例行工作,并且本质上输出第一个片段的代码。然后,我可以在闲暇时手动在类主体的其余部分添加设置器。

这似乎是一个足够常见的用例,但我无法找到让它发挥作用的方法。冻结参数最接近我想要的,但它的行为并不像@property,因为它排除了任何类型的设置器。

python properties python-dataclasses

5
推荐指数
0
解决办法
2203
查看次数

是否可以在 __post_init__() 或更高版本中冻结数据类对象?

我想知道是否可以在post_init () 中甚至在定义对象之后“冻结”数据类对象。

所以而不是:

@dataclass(frozen=True)
class ClassName:
    var1: type = value
Run Code Online (Sandbox Code Playgroud)

有类似的东西:

@dataclass
class ClassName:
     var1: type = None
def __post_init__(self):
     self.var1 = value
     FREEZE()
Run Code Online (Sandbox Code Playgroud)

甚至像这样:

a = ClassName()
FREEZE(a)
Run Code Online (Sandbox Code Playgroud)

可能与否,为什么?

python python-dataclasses

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

将 python fire 与 dataclass 结合起来

我有一个如下所示的代码,其中包含用于各种计算的多个函数。

我使用python fire来传递参数,而不是定义 argparse 并从 cli 调用函数。每次添加新参数时,我都必须self在 init 中添加它。我正在寻找更好的方法。

我发现 python数据类可以解决这个问题。我研究了 python fire命令分组多个命令

class MyClass:
    def __init__(
        self,
        input_path: str,
        output_path: str = '',
        same_size: bool = False,
        crop_size: int = 300,
        padding: int = 20,
        write_json: bool = False,
        write_image: bool = False,
        line_thickness: int = 2,
        side_color: Tuple = (255, 255, 0),
        top_color: Tuple = (255, 0, 0),
    ) -> None:
        super(MyClass, self).__init__()
        self.input_path = input_path
        self.output_path = …
Run Code Online (Sandbox Code Playgroud)

python command-line-interface python-dataclasses python-fire

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

用类型值注释数据类类变量

我们有许多数据类,代表具有共同祖先的各种结果Result。然后,每个结果使用其自己的 子类提供其数据ResultData。但我们很难正确注释该案例。

我们想出了以下解决方案:

from dataclasses import dataclass
from typing import ClassVar, Generic, Optional, Sequence, Type, TypeVar


class ResultData:
    ...


T = TypeVar('T', bound=ResultData)


@dataclass
class Result(Generic[T]):
    _data_cls: ClassVar[Type[T]]
    data: Sequence[T]

    @classmethod
    def parse(cls, ...) -> T:
        self = cls()
        self.data = [self._data_cls.parse(...)]
        return self

class FooResultData(ResultData):
    ...

class FooResult(Result):
    _data_cls = FooResultData
Run Code Online (Sandbox Code Playgroud)

但它最近因 mypy error 停止工作ClassVar cannot contain type variables [misc]。它也反对 PEP 526,请参阅https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations,我们之前错过了。

有没有办法正确注释这个案例?

python mypy python-dataclasses

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

在 dataclasses.field 中使用显式 __init__ 构造函数和 default_factory 参数时,数据类属性丢失

以下代码创建一个Obj带有 int 字段n(默认值为 0)的数据类。

from dataclasses import dataclass, field

@dataclass
class Obj:
    n: int = field(default_factory=int)
    
a = Obj()
print(a.n)
Run Code Online (Sandbox Code Playgroud)
a.n = 0
Run Code Online (Sandbox Code Playgroud)

现在,添加一个显式__init__构造函数:

a.n = 0
Run Code Online (Sandbox Code Playgroud)

它现在生成此错误,声称该Obj对象没有名为 的属性n

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [6], in <module>
      8         pass
     10 a = Obj()
---> 11 print(f'a.n = {a.n}')

AttributeError: 'Obj' object has no attribute 'n'
Run Code Online (Sandbox Code Playgroud)

我想也许显式__init__会覆盖field()正在执行的任何操作,但是如果我们从参数更改default_factorydefault,它会再次起作用:

@dataclass
class …
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses

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