我试图比较从公共基类(也是@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)
我该如何解决这个问题?
考虑一个参数具有可变默认值的数据类。为了能够使用新的默认值实例化一个对象而不是共享可变对象,我们可以这样做:
@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?
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__它之外)?
我有以下数据类。
@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。
我有包含其他数据类作为其字段的数据类:
@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)
但我不知道如何正确编写它。
我想使用 @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,因为它排除了任何类型的设置器。
我想知道是否可以在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 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
我们有许多数据类,代表具有共同祖先的各种结果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,我们之前错过了。
有没有办法正确注释这个案例?
以下代码创建一个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_factory为default,它会再次起作用:
@dataclass
class …Run Code Online (Sandbox Code Playgroud)