繁体   English   中英

以编程方式扩展数据类'__repr__

[英]Extend dataclass' __repr__ programmatically

假设我有一个带有 set 方法的数据类。 如何扩展 repr 方法,以便在调用 set 方法时它也会更新:

from dataclasses import dataclass
@dataclass
class State:
    A: int = 1
    B: int = 2
    def set(self, var, val):
        setattr(self, var, val)

前任:

In [2]: x = State()

In [3]: x
Out[3]: State(A=1, B=2)

In [4]: x.set("C", 3)

In [5]: x
Out[5]: State(A=1, B=2)

In [6]: x.C
Out[6]: 3

我想要的结果

In [7]: x
Out[7]: State(A=1, B=2, C=3)

dataclass装饰器使您可以快速轻松地构建具有特定字段的类,这些字段在您定义 class 时预先确定。 但是,您打算使用 class 的方式与数据类的用途不太匹配。 您希望能够在 class 已经存在之后动态添加新字段,并让它们使用各种方法(如__init____repr__和大概__eq__ )。 这几乎消除了使用dataclass的所有好处。 相反,您应该编写自己的 class 来执行您想要的操作。

这是一个快速而肮脏的版本:

class State:
    _defaults = {"A": 1, "B": 2}
    
    def __init__(self, **kwargs):
        self.__dict__.update(self._defaults)
        self.__dict__.update(kwargs)
        
    def __eq__(self, other):
        return self.__dict__ == other.__dict__ # you might want to add some type checking here
        
    def __repr__(self):
        kws = [f"{key}={value!r}" for key, value in self.__dict__.items()]
        return "{}({})".format(type(self).__name__, ", ".join(kws))

这与您从types.SimpleNamespace获得的内容非常相似,因此您可能只能使用它(尽管它不执行默认值)。

您可以将您的set方法添加到此框架中,但在我看来,这似乎是您已经用来实现它的内置setattr function 的不必要重复。 如果调用者需要动态设置属性,可以自己调用setattr 如果属性名称是常量,他们可以使用普通的属性赋值语法来代替s.foo = "bar"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM