python 如何将大量的构造函数参数打包到单独的对象中?

How to pack a lot of constructor parameters into separate object in python?

例如这段代码创建了一个带有一些内容的标签 可以是文本、位图等

label1 = tk.Label(text="Hello", font=("Arial",32,"bold"), bg="grey", fg="red",width=200,height=200) #and so on...

我无法真正重构 tk.Label 构造函数处理事物的方式,也无法更改它。 在我的例子中,我想在一个单独的对象中配置文本/字体。 所有样式都在另一个对象中,width/height 又在另一个对象中。

像这样:

size_config = ElementSize(width=200,height=200)
styling_config = Style(bg="red",fg="blue")
text_config = ...

# then create label with this objects

这只是一个例子。我经常对 python 库使用构造函数的糟糕程度感到沮丧,我不知道如何处理这 9000 多个完全没有结构的参数。

是不是我哪里出了问题? 有一种方法可以将所有这些东西隐藏在某种范围内的对象中,然后将它们映射到构造函数中的所有这些噩梦吗?

使用**kwargs解包。

label_args = dict(
    text="Hello",
    font=("Arial",32,"bold"),
    bg="grey",
    fg="red",
    width=200,
    height=200,
) #and so on...

label1 = tk.Label(**label_args)

如果你想对这些东西应用静态类型,你可以为每个函数签名定义 TypedDicts。

为什么不用自己的函数?

from inspect import getfullargspec


class Label:
    def __init__(self, text, font, bg, fg, width, height):
        self.text = text
        self.font = font
        self.bg = bg
        self.fg = fg
        self.width = width
        self.height = height
        print("created a label")


class ElementSize:
    def __init__(self, width, height):
        self.width = width
        self.height = height


class Background:
    def __init__(self, bg):
        self.bg = bg


def map_arguments(argument_sources, cls, **kwargs):
    arguments = dict()
    for argument_source in argument_sources:
        argument_source_signature = getfullargspec(argument_source.__init__).args
        for arg in argument_source_signature:
            if arg == "self":
                continue
            arguments[arg] = argument_source.__getattribute__(arg)
    arguments.update(kwargs)
    return cls(**arguments)


if __name__ == '__main__':
    label = map_arguments([ElementSize(2, 4), Background("grey")], Label, fg="red", text="Hello",
                          font=("Arial", 32, "bold"))