Dataclass字段可以格式化其为reter的值吗?
我有一个以HEX和HSV形式持有RGB数据的节点类。我将使用它以各种方式对颜色进行排序,并且希望HSV元组保持浮动形式进行比较,而不是从字符串中转换为每种用途。是否有一种方法可以指定Dataclass字段,它应该以类似于默认值的特定方式格式化值,而default_factory
,即A repr_factory
?
def RGB2HSV(r, g, b):
'''Returns HSV values in the range H = [0, 360], S = [0, 100], V = [0, 100]'''
r, g, b = r / 255, g / 255, b / 255
maxRGB = max(r, g, b)
minRGB = min(r, g, b)
delta = maxRGB - minRGB
V = maxRGB
if V == 0:
return 0, 0, V
S = delta / V * 100
if S == 0:
return 0, S, V * 100
if V == r:
H = (g - b) / delta
elif V == g:
H = 2 + (b - r) / delta
else:
H = 4 + (r - g) / delta
H *= 60
if H < 0:
H += 360
return H, S, V * 100
@dataclass
class Node:
r: int = field(repr=False)
g: int = field(repr=False)
b: int = field(repr=False)
hex: tuple[int, int, int] = field(init=False)
hsv: tuple[float, float, float] = field(init=False)
def __post_init__(self):
self.hex = self.r, self.g, self.b # Generating random r, g, b numbers
self.hsv = RGB2HSV(self.hex) # Converts the r, g, b to a tuple of floats
当我研究各种各样的情况时,我正在打印节点,看到10个不必要的浮点数是分散注意力的。据我所知,我会更好地实施自己的__ epr __
,而不是依靠生成的数据级别?
我要查看__ repl __
值的原因是因为它是由数据级别自动生成的,并且可以使几乎相同的颜色更容易区分几乎相同的颜色,而不是仅查看视觉输出。如果我知道颜色是什么是实际数字,则更容易找出要更改或下一步的事情。输出末尾的一部分:
Node(hex=(238, 0, 0), hsv=(0.0, 100.0, 93.33333333333333))
Node(hex=(238, 17, 0), hsv=(4.285714285714286, 100.0, 93.33333333333333))
Node(hex=(238, 34, 0), hsv=(8.571428571428571, 100.0, 93.33333333333333))
Node(hex=(238, 51, 0), hsv=(12.857142857142858, 100.0, 93.33333333333333))
Node(hex=(255, 0, 0), hsv=(0.0, 100.0, 100.0))
Node(hex=(255, 17, 0), hsv=(4.0, 100.0, 100.0))
Node(hex=(255, 34, 0), hsv=(8.0, 100.0, 100.0))
Node(hex=(255, 51, 0), hsv=(12.0, 100.0, 100.0))
基本上,可以将格式指定到数据级字段,类似于如何将函数指定到default_factory
,以便生成的__repr __
要为我格式化字段,所以我不必写自己的?
...
hsv: tuple[float, float, float] = field(init=False, repr_factory=lambda x: "{:.3f"}.format(x) for x in self.hsv)
...
Node(hex=(238, 51, 0), hsv=(12.857, 100.000, 93.333))
I have a Node class holding RGB data in both hex and HSV form. I'll be using this to sort colors in various ways and would prefer the HSV tuple to remain in float form for comparisons instead of converting from a string for every use. Is there a way to specify to the dataclass field that it should format the value in a specific way similar to default values with the default_factory
, i.e. a repr_factory
?
def RGB2HSV(r, g, b):
'''Returns HSV values in the range H = [0, 360], S = [0, 100], V = [0, 100]'''
r, g, b = r / 255, g / 255, b / 255
maxRGB = max(r, g, b)
minRGB = min(r, g, b)
delta = maxRGB - minRGB
V = maxRGB
if V == 0:
return 0, 0, V
S = delta / V * 100
if S == 0:
return 0, S, V * 100
if V == r:
H = (g - b) / delta
elif V == g:
H = 2 + (b - r) / delta
else:
H = 4 + (r - g) / delta
H *= 60
if H < 0:
H += 360
return H, S, V * 100
@dataclass
class Node:
r: int = field(repr=False)
g: int = field(repr=False)
b: int = field(repr=False)
hex: tuple[int, int, int] = field(init=False)
hsv: tuple[float, float, float] = field(init=False)
def __post_init__(self):
self.hex = self.r, self.g, self.b # Generating random r, g, b numbers
self.hsv = RGB2HSV(self.hex) # Converts the r, g, b to a tuple of floats
While I'm working out the different sorts, I'm printing out the Nodes and seeing 10 unnecessary digits of a float is distracting. As far as I can think of, would I just be better off implementing my own __repr__
for the class instead of relying on the dataclass generated one?
The reason I'm looking at the __repr__
value is because it's automatically generated by the dataclass and can make distinguishing between nearly identical colors easier than just looking at the visual output. It'll be easier to find out what to change or do next if I know what the actual numbers a color are. A portion of the end of the output:
Node(hex=(238, 0, 0), hsv=(0.0, 100.0, 93.33333333333333))
Node(hex=(238, 17, 0), hsv=(4.285714285714286, 100.0, 93.33333333333333))
Node(hex=(238, 34, 0), hsv=(8.571428571428571, 100.0, 93.33333333333333))
Node(hex=(238, 51, 0), hsv=(12.857142857142858, 100.0, 93.33333333333333))
Node(hex=(255, 0, 0), hsv=(0.0, 100.0, 100.0))
Node(hex=(255, 17, 0), hsv=(4.0, 100.0, 100.0))
Node(hex=(255, 34, 0), hsv=(8.0, 100.0, 100.0))
Node(hex=(255, 51, 0), hsv=(12.0, 100.0, 100.0))
Basically, can a format be specified to a dataclass field, similar to how a function can be specified to default_factory
, in order for the generated __repr__
to format the field for me so I don't have to write my own?
...
hsv: tuple[float, float, float] = field(init=False, repr_factory=lambda x: "{:.3f"}.format(x) for x in self.hsv)
...
Node(hex=(238, 51, 0), hsv=(12.857, 100.000, 93.333))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Dataclasses库当前不支持这样的格式字段。默认
__ epr __
在每个随附的字段中生成的代码始终位于f'field = {self.field!r}'
中。您将必须编写自己的__ epr __
。The dataclasses library currently does not support formatting fields like that. The code generated in the default
__repr__
for each included field is always in the formf'field={self.field!r}'
. You will have to write your own__repr__
.这是基于 jasmijn的答案我们必须编写我们自己的
__ epr__ 。我敢肯定,我可能会以最糟糕的方式处理字段,但这是一个开始。用更好的方法替换尴尬的字段名称和值访问。
输出(修改为原始):
Here's a working proof-of-concept implementation based on Jasmijn's answer that we must write our own
__repr__
. I'm sure that I probably processed the fields in the worst way possible, but this is a start. Replace the awkward field name and value access with a better method.Output (Modified then Original):