使用任意替换的属性名创建Python类

creating Python classes with arbitrarily substituted attribute name

我很抱歉没有给这个问题一个更好的标题;我之所以发表这个标题,是因为我甚至没有正确的术语来知道我在寻找什么。

我定义了一个具有"spam"属性的类:

1
2
3
4
5
def SpamClass(object):
    def __init__(self, arg):
        self.spam = arg
    def __str__(self):
        return self.spam

我想创建一个(子/同级?)类,其功能完全相同,但具有名为"eggs"而不是"spam"的属性:

1
2
3
4
5
def EggsClass(object):
    def __init__(self, arg):
        self.eggs = arg
    def __str__(self):
        return self.eggs

概括地说,如何创建具有任意属性名的功能相同的类?当类具有复杂的行为时,复制代码似乎很愚蠢。

更新:我同意这闻起来像是糟糕的设计。澄清一下,我不是想用这种愚蠢的方式来解决一个特定的问题。我只想知道如何在保留功能的同时随意命名对象的__dict__的(非魔法)内容。考虑一些类似于dict类对象的keys()方法。人们用keys()方法创建各种类,这些方法的行为符合约定,命名约定是一件好事。但是名字是任意的。我怎样才能用一个完全替换keys()spam()方法生成一个类,而不需要在源代码中手动替换/keys/spam/?

重载__getattr__和朋友引用泛型属性对我来说似乎是不雅和脆弱的。如果子类重新实现这些方法,它必须适应这种行为。我希望在用户看来,只有一个具有命名属性的基类可以被天真地访问。

实际上,我可以想到一个合理的用例。假设您想要一个mixin类,它提供一个特殊的属性和一些密切相关的方法来操作或依赖这个属性。在重用底层行为时,用户可能希望为不同的类(以匹配实际问题域中的名称或避免名称冲突)不同地命名此特殊属性。


这是一种获得我认为你想要的效果的方法。

用通用属性名定义通用类。然后在每个子类中,遵循http://docs.python.org/reference/datamodel.html自定义属性访问中的建议,使属性在外部看起来像您想要调用的任何对象一样。

你对你所做的事情的描述让我觉得它有一种"代码味道",我建议你仔细检查一下你的设计,看看这是否真的是你想要做的。但你可以按照我的建议来做。


要在运行时创建属性,只需将它们添加到类代码的self.__dict__['foo'] = 'I'm foo'中。


你是否考虑过不要过于复杂化,只创建一个类?(因为它们还是一样的)

1
2
3
4
5
6
7
class FoodClass(object):
    def __init__(self, foodname, arg):
        self.attrs = {foodname: arg}
        self.foodname = foodname

    def __str__(self):
        return self.attrs[foodname]

如果需要一些好的构造函数,只需分别创建它们:

1
2
3
4
5
def make_eggs(arg):
    return FoodClass('eggs', arg)

def make_spam(arg):
    return FoodClass('spam', arg)


您还可以创建一个具有所有公共内容的超级类,然后创建具有特定属性的子类。

甚至:

1
2
3
4
5
6
7
8
9
10
11
12
def SuperClass(object):
    specific_attribute = 'unset'

    def __init__(self, arg):
        setattr(self, specific_attribute, arg)

    def __str__(self):
        return getattr(self, specific_attribute)


def EggClass(SuperClass):
    specific_attribute = 'eggs'