Ton*_*ock 7 python repr python-dataclasses
概括
我有dataclass10多个字段。print()使用它们将有趣的上下文埋藏在默认值的墙中 - 让我们通过不再不必要地重复这些来使它们变得更友好。
Python 中的数据类
Python 的@dataclasses.dataclass()( PEP 557 ) 提供自动可打印表示 ( __repr__())。
假设这个例子,基于 python.org 的:
from dataclasses import dataclass
@dataclass
class InventoryItem:
name: str
unit_price: float = 1.00
quantity_on_hand: int = 0
Run Code Online (Sandbox Code Playgroud)
装饰器@dataclass(repr=True)(默认)将得到print()一个很好的输出:
InventoryItem(name='Apple', unit_price='1.00', quantity_on_hand=0)
Run Code Online (Sandbox Code Playgroud)
我想要的:跳过打印默认值
repr它会打印所有字段,包括您不想显示的隐含默认值。
print(InventoryItem("Apple"))
# Outputs: InventoryItem(name='Apple', unit_price='1.00', quantity_on_hand=0)
# I want: InventoryItem(name='Apple')
Run Code Online (Sandbox Code Playgroud)
print(InventoryItem("Apple", unit_price="1.05"))
# Outputs: InventoryItem(name='Apple', unit_price='1.05', quantity_on_hand=0)
# I want: InventoryItem(name='Apple', unit_price='1.05')
Run Code Online (Sandbox Code Playgroud)
print(InventoryItem("Apple", quantity_on_hand=3))
# Outputs: InventoryItem(name='Apple', unit_price=1.00, quantity_on_hand=3)
# I want: InventoryItem(name='Apple', quantity_on_hand=3)
Run Code Online (Sandbox Code Playgroud)
print(InventoryItem("Apple", unit_price='2.10', quantity_on_hand=3))
# Output is fine (everything's custom):
# InventoryItem(name='Apple', unit_price=2.10, quantity_on_hand=3)
Run Code Online (Sandbox Code Playgroud)
讨论
dataclass repr在内部,这是python 的 -generator机制3.10.4:->cls.__repr__=_repr_fn(flds, globals))_recursive_repr(fn)
@dataclass(repr=False)可能是关闭再def __repr__(self):添加的情况。
如果是这样,那会是什么样子?我们不想包含可选的默认值。
语境
重复一遍,在实践中,我的dataclass有10 多个字段。
我print()通过运行代码和 repl 来获取实例,并@pytest.mark.parametrize在使用-vvv.
大数据类的非默认值(有时是输入)是不可能看到的,因为它们被隐藏在默认字段中,更糟糕的是,每个非默认值都大得不成比例且令人分心:掩盖了打印的其他有价值的内容。
相关问题
截至今天,还没有太多dataclass问题(这可能会改变):
你可以这样做:
import dataclasses
from dataclasses import dataclass
from operator import attrgetter
@dataclass(repr=False)
class InventoryItem:
name: str
unit_price: float = 1.00
quantity_on_hand: int = 0
def __repr__(self):
nodef_f_vals = (
(f.name, attrgetter(f.name)(self))
for f in dataclasses.fields(self)
if attrgetter(f.name)(self) != f.default
)
nodef_f_repr = ", ".join(f"{name}={value}" for name, value in nodef_f_vals)
return f"{self.__class__.__name__}({nodef_f_repr})"
# Prints: InventoryItem(name=Apple)
print(InventoryItem("Apple"))
# Prints: InventoryItem(name=Apple,unit_price=1.05)
print(InventoryItem("Apple", unit_price="1.05"))
# Prints: InventoryItem(name=Apple,unit_price=2.10,quantity_on_hand=3)
print(InventoryItem("Apple", unit_price='2.10', quantity_on_hand=3))
Run Code Online (Sandbox Code Playgroud)