python - 从 python `dataclass` `__repr__` 中排除默认字段

标签 python python-dataclasses repr

总结

我有一个包含 10 多个字段数据类print()将它们隐藏在默认值墙中的有趣上下文 - 让我们通过避免不必要地重复这些来使它们更友好。

Python 中的数据类

Python 的 @dataclasses.dataclass() ( PEP 557 ) 提供自动打印表示 ( __repr__() )。

假设这个例子,based on python.org's :

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): 的情况。

如果是这样,那会是什么样子?我们不想包含可选的默认值。

上下文

重复一下,在实践中,我的数据类10+个字段

我通过运行代码和 repl 来print()ing 实例,并且 @pytest.mark.parametrize运行时 pytest使用 -vvv

大数据类的非默认值(有时是输入)是不可能看到的,因为它们被埋在默认字段中,更糟糕的是,每一个都非常大且令人分心:掩盖了打印出来的其他有值(value)的东西。

相关问题

截至今天,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))

关于python - 从 python `dataclass` `__repr__` 中排除默认字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72161257/

相关文章:

python - 如何定义两个位置参数的互斥组?

python - 在通过关闭窗口销毁第一个实例后创建第二个 tkinter Tk() 是不好的做法吗?

python - 从 **kwargs 实例化多个对象的 pythonic 方法是什么?

python - 在另一个函数中用作参数时,如何将自定义 Python 对象表示为字符串?

python - 在对象字典上调用 str

python - python 中的列表排列

python - 无法获取英文搜索结果

python - 你能在每次修改另一个字段时修改一个对象的字段吗?

python - 如何在 Python 中将对象 A 中的数据合并到对象 B 中?

python - 在Python中以最大精度打印十进制数字而不带尾随零的最佳方法