【问题标题】:How to specify Python class attributes with constructor keyword arguments如何使用构造函数关键字参数指定 Python 类属性
【发布时间】:2025-12-10 15:25:01
【问题描述】:

我试图想出一种方法来允许在实例化时指定任意数量的类属性,这与字典非常相似。理想用例:

>>> instance = BlankStruct(spam=0, eggs=1)
>>> instance.spam
0
>>> instance.eggs
1

BlankStruct 定义为:

class BlankStruct(Specifiable):
    @Specifiable.specifiable
    def __init__(self, **kwargs):
        pass

我正在考虑使用父类装饰器,但在思考是否使用实例方法、类方法或静态方法(或者可能不使用以上任何方法!)时迷失了方向。这是迄今为止我想出的最好的,但问题是属性被应用于类而不是实例:

class Specifiable:
    @classmethod
    def specifiable(cls, constructor):
        def constructor_wrapper(*args, **kwargs):
            constructor(*args, **kwargs)
            cls.set_attrs(**kwargs)
        return constructor_wrapper

    @classmethod
    def set_attrs(cls, **kwargs):
        for key in kwargs:
            setattr(cls, key, kwargs[key])

这样的父类怎么做?


注意: 是的,我知道我想做的是不好的做法。但有时你只需要按照老板告诉你的去做。

【问题讨论】:

  • 是因为这是一个问得不好的问题,还是因为我试图做的事情不被接受?如果是前者:好的,请发表评论或建议编辑。如果是后者:这似乎没有必要。好的/坏的做法可以在答案和 cmets 中解决,这对未来的读者很有帮助。
  • 什么是@Specifiable.specifiable??顺便说一句,我没有投反对票,只是注意到这个问题是一年前的......
  • @juanpa.arrivillaga 这是我为帮助我实现BlankStruct 所需功能而创建的父类。 (不过,正如问题中所述,它没有按预期工作。)它在第三个代码块中定义。

标签: python class decorator


【解决方案1】:

是的,您可以执行以下操作,但我不建议这样做,因为这显然违反了显式优于隐式的原则:

class BlankStruct:

    def __init__(self, **attrs):
        self.__dict__.update(**attrs)
    def __getattr__(self, attr):
        return self.__dict__.get(attr, None)

f = BlankStruct(spam=0, eggs=1)

更完整的回复是here 并启发了这个答案。

我建议明确你希望你的班级拥有的属性。否则,您将得到一个具有高度可变性的类,这可能会降低它的实用性。

【讨论】:

    【解决方案2】:

    我相信你可以在没有装饰器的情况下做到这一点:

    class Specifiable:
    
      def __init__(self, **kwargs):
        for key, value in kwargs.items():
          setattr(self, key, value)
    
    
    class BlankStruct(Specifiable):
    
      def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # Do other stuff.
    

    【讨论】: