标准Python基类作为任意属性的容器

Standard Python base class as a container for arbitrary attributes

只是问这个问题,因为它似乎是一个定期出现的模式,我想知道是否有人知道支持这个模式的标准库功能,或者一个单行程序,可能做了一些等效的事情。

如果我想定义一个类来传递数据,这个类可以包含任意属性,在构造时可以进行如下设置:

1
2
3
4
>>> class Splat:
        def __init__(self, **args):
            for k, v in args:
                setattr(self, k, v)

然后像这样使用:

1
2
3
>>> s = Splat(attr1='burp', attr2='gurt', attr3='sint')
>>> vars(s)
{'attr2': 'gurt', 'attr3': 'sint', 'attr1': 'burp'}

这是我在python标准库(ssl.wrapSocket中看到的一种模式,如果内存可用的话,也可以在库中看到类似的模式),并且我认为它在一般情况下足够有用,以至于有一种常用的python习惯用法或混合方法,我可以利用它,而不必在需要的时候创建自己的习惯用法。

我知道在我需要的时候只包括四行,但是为了节约起见,我想知道我是否可以使用0或至少1行的变体。也许这样:

1
s = TheBaseClass({'attr2': 'gurt', 'attr3': 'sint', 'attr1': 'burp'})

1
2
class Splat(TheBaseClass):
    pass

有些人可能会很快跳进去说"使用dict",但我在想一些用例,在这些用例中,人们可能希望模拟现有的对象类型(duck类型),并推断它是一个特定的"类型"(就像这个功能只是用作mixin)。

编辑:同样的,像EDOCX1[1]这样的结构的一个问题是我没有必要声明它,或者在类型安全方面得到很多…


这有点像用推土机撞钉子……但是argparse定义了一个Namespace类,它可以做到:

1
2
import argparse
print(argparse.Namespace(a=1, b=2))

你总是可以从中得到:

1
2
3
import argparse
class X(argparse.Namespace): pass
print(X(a=1, b=2))

不过,我并不建议你这么做,因为这有点…恶心…

至少你可以免费得到__str____repr__