概述
我有一个包含10个以上字段的dataclass
。使用print()
命令会将有趣的内容深埋在默认值中 - 让我们通过不需要重复这些值来使它们更加友好。
Python中的Dataclasses
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
装饰器通过
@dataclass(repr=True)
(默认)将会 print()
一个漂亮的输出:InventoryItem(name='Apple', unit_price='1.00', quantity_on_hand=0)
我想要的是:跳过打印默认值。
`repr`会打印出所有字段,包括你不想显示的隐含默认值。
print(InventoryItem("Apple"))
# Outputs: InventoryItem(name='Apple', unit_price='1.00', quantity_on_hand=0)
# I want: InventoryItem(name='Apple')
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')
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)
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)
讨论
在Python 3.10.4
中,dataclass
repr
生成器的内部机制如下:cls.__repr__
=
_repr_fn(flds, globals))
-> _recursive_repr(fn)
如果需要关闭 @dataclass(repr=False)
并添加 def __repr__(self):
,该怎么做呢?我们不想包含可选默认值。
背景
重申一下,在实践中,我的 dataclass
具有10多个字段。
print()
实例,并在使用-vvv
运行pytest时,使用@pytest.mark.parametrize
。
由于默认字段的存在,很难看到大型数据类的非默认值(有时是输入),更糟糕的是,每个非默认值都异常巨大且分散:遮盖了其他有价值的内容。
相关问题
截至今天,dataclass
问题并不多(这可能会改变):
- 通过编程方式扩展数据类的 __repr__ 方法:该方法旨在限制 repr 的显示,除非它们被明确地覆盖,否则应该显示较少的字段。
- Python 数据类生成哈希并排除不安全字段:该方法用于哈希,与默认值无关。
repr=False
是否真的必要(现在无法测试)- 定义__repr__
不会覆盖内置方法吗? - fsimonjetz__repr__
。 - user2246849def __repr__
藏在更复杂的类中的深处。 - fsimonjetzlibvcs.utils.dataclasses.SkipDefaultFieldsMixin
,以及用法和文档。我添加了doctests。当将其用作子类时,需要向@dataclasses.dataclass
传递repr=False
。直接使用__repr__
时可以省略它。 - tony