如果我创建一个包含 Numpy ndarray 的 Python 数据类,我将无法再使用自动生成的数据类__eq__。
import numpy as np
@dataclass
class Instr:
foo: np.ndarray
bar: np.ndarray
arr = np.array([1])
arr2 = np.array([1, 2])
print(Instr(arr, arr) == Instr(arr2, arr2))
Run Code Online (Sandbox Code Playgroud)
ValueError:包含多个元素的数组的真值不明确。使用 a.any() 或 a.all()
这是因为ndarray.__eq__ 有时返回ndarray真值,通过比较a[0]来b[0],等等等等到2。这是相当复杂的,不直观的时间越长,而实际上只提高在阵列不同的形状,或者有错误不同的价值观什么的。
如何安全地比较@dataclasses 持有 Numpy 数组?
@dataclass的实现__eq__是使用生成的eval()。它的源在堆栈跟踪中丢失,无法使用 来查看inspect,但它实际上使用的是调用 bool(foo)的元组比较。
import dis
dis.dis(Instr.__eq__)
Run Code Online (Sandbox Code Playgroud)
摘抄:
Run Code Online (Sandbox Code Playgroud)3 12 LOAD_FAST 0 (self) 14 LOAD_ATTR 1 (foo) 16 LOAD_FAST 0 (self) …
我试图导出id_from的默认值name,反之亦然。
@dataclass
class Item:
id_ = NAME_TO_ID[name]
name = ID_TO_NAME[id_]
Run Code Online (Sandbox Code Playgroud)
我应该能够像这样调用该类:
Item(id_=123)
Item(name='foo')
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我还希望类在提供id_和时引发错误。name
Item(id_=123, name='foo') # ValueError: id_ and name cannot be provided together
Run Code Online (Sandbox Code Playgroud)
关于我应该如何去做这件事有什么建议吗?
我想在创建数据类时使用Union和Optional类型。我可以安全地使用这些类型吗?
例如:
@dataclass
class Car:
year: int
owner: Optional[str]
engine: Union[Engine1, Engine2]
Run Code Online (Sandbox Code Playgroud) 我有一个带有可变字段(列表)的数据类。我希望实现的是,即使在 __init__ 调用中显式设置为 None ,该字段也永远不会为 None 。在普通的类中,实现起来很简单:
class A:
def __init__(self, l: Optional[List[int]] = None):
if l is None:
l = []
self.l = l
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以仅使用dataclasses.field函数来实现相同的结果,即无需显式实现 __init__ 方法(当类有很多属性时,这会很麻烦)?default_factory当提供的 init 参数为 None 时,我可以强制 dataclasses.field 调用它吗?
我想将数据类序列化为字符串。dataclasses.asdict创建自定义方法就足够简单了__str__。即使对于具有其他数据类或其列表作为成员的类,它也能完美运行。但是,调用str数据类列表会生成repr版本。我想str生成序列化表格并repr保持原样。
import json
from dataclasses import dataclass, asdict
@dataclass
class Ser:
def __repr__(self):
print('repr called')
return json.dumps(asdict(self))
def __str__(self):
print('str called')
return json.dumps(asdict(self))
@dataclass(repr=False)
class C(Ser):
i: int
def __str__(self):
print('child str called')
return super().__str__()
list_in = json.loads('[{"i": 1}, {"i": 2}]')
data = [C(**i) for i in list_in]
print(data)
print(repr(data))
print(str(data))
Run Code Online (Sandbox Code Playgroud)
上面脚本的输出是:
repr called
repr called
[{"i": 1}, {"i": 2}]
repr called
repr called
[{"i": 1}, {"i": 2}] …Run Code Online (Sandbox Code Playgroud) 为属性设置默认值时,我可以调用在类外部定义的函数,但不能调用类内定义的方法。
请参阅下面的示例。
进口:
from dataclasses import dataclass, field
Run Code Online (Sandbox Code Playgroud)
call_that()外部定义工作正常:
def call_that():
return -1
@dataclass
class Foo:
myvar : int = field(default_factory = call_that)
Foo()
Run Code Online (Sandbox Code Playgroud)
返回“Foo(myvar=-1)”
但call_this()里面定义了
@dataclass
class Foo:
myvar : int = field(default_factory = call_this)
def call_this():
return 1
Foo()
Run Code Online (Sandbox Code Playgroud)
返回“NameError:名称'call_this'未定义”
如何使用字典更新数据类的字段?
例子:
@dataclass
class Sample:
field1: str
field2: str
field3: str
field4: str
sample = Sample('field1_value1', 'field2_value1', 'field3_value1', 'field4_value1')
updated_values = {'field1': 'field1_value2', 'field3': 'field3_value2'}
Run Code Online (Sandbox Code Playgroud)
我想做类似的事情
sample.update(updated_values)
Run Code Online (Sandbox Code Playgroud) 我是 python 数据类的新手,想知道是否有一种聪明的方法来定义 python 数据类中的字段约束。
假设我们有一个数据类“SomeConfiguration”,有 3 个字段(field1、field2、field3),它们都是浮点数。我所处的环境中经常创建配置对象,并且字段是随机分配的,并且我想确保始终满足字段的某些约束。例如以下约束:2 * field1 > (-1) * field3
使用数据类执行此操作的最佳和最有效的方法是什么?
一些上下文信息:我有几个配置类,它们都是“配置”类型。在所有不同的配置类上必须定义不同的约束。
例子:
@dataclass
class SomeConfiguration(Configuration):
field1: float
field2: float
field3: float
config = create_random_configuration()
for field in fields(config):
check_if_constraints_for_field_are_met(field, config)
Run Code Online (Sandbox Code Playgroud) 我遇到一种情况,我希望能够将冻结的dataclass实例视为始终拥有最新数据。或者换句话说,我希望能够检测数据类实例是否已replace调用它并抛出异常。它还应该仅适用于该特定实例,以便相同类型的其他数据类实例的创建/替换不会相互影响。
这是一些示例代码:
from dataclasses import dataclass, replace
@dataclass(frozen=True)
class AlwaysFreshData:
fresh_data: str
def attempt_to_read_stale_data():
original = AlwaysFreshData(fresh_data="fresh")
unaffected = AlwaysFreshData(fresh_data="not affected")
print(original.fresh_data)
new = replace(original, fresh_data="even fresher")
print(original.fresh_data) # I want this to trigger an exception now
print(new.fresh_data)
Run Code Online (Sandbox Code Playgroud)
这里的想法是防止意外突变和从我们的数据类对象中读取过时的内容,以防止错误。
可以这样做吗?通过基类还是其他方法?
编辑:这里的目的是有一种强制/验证数据类的“所有权”语义的方法,即使它只是在运行时。
这是常规数据类有问题的情况的具体示例。
@dataclass
class MutableData:
my_string: str
def sneaky_modify_data(data: MutableData) -> None:
some_side_effect(data)
data.my_string = "something else" # Sneaky string modification
x = MutableData(my_string="hello")
sneaky_modify_data(x)
assert x.my_string == "hello" # as a caller of …Run Code Online (Sandbox Code Playgroud) 我使用数据类创建嵌套数据结构,用它来表示复杂的测试输出。
以前,我一直通过创建多个顶级数据类然后使用组合来创建层次结构:
from dataclasses import dataclass
@dataclass
class Meta:
color: str
size: float
@dataclass
class Point:
x: float
y: float
stuff: Meta
point1 = Point(x=5, y=-5, stuff=Meta(color='blue', size=20))
Run Code Online (Sandbox Code Playgroud)
我想知道是否有一种方法以独立的方式定义类,而不是用一堆较低级别的类污染我的顶级。所以上面, dataclass 的定义Point包含 的定义Meta,而不是顶层的定义。
我想知道是否可以将内部(数据类)类与数据类一起使用并使一切正常工作。
所以我尝试了这个:
rom dataclasses import dataclass
from typing import get_type_hints
@dataclass
class Point:
@dataclass
class Meta:
color: str
size: float
@dataclass
class Misc:
elemA: bool
elemB: int
x: float
y: float
meta: Meta
misc: Misc
point1 = Point(x=1, y=2,
meta=Point.Meta(color='red', size=5.5), …Run Code Online (Sandbox Code Playgroud)