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

时间:2011-02-11 07:16:04

标签: python attributes introspection metaclass

我为没有给这个问题更好的标题而道歉;我发布它的原因是我甚至没有正确的术语来了解我在寻找什么。

我已经定义了一个属性为'spam'的类:

def SpamClass(object):
    def __init__(self, arg):
        self.spam = arg
    def __str__(self):
        return self.spam

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

def EggsClass(object):
    def __init__(self, arg):
        self.eggs = arg
    def __str__(self):
        return self.eggs

总结一下,如何使用任意属性名创建功能相同的类?当类具有复杂的行为时,重复代码似乎很愚蠢。

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

重载__getattr__和朋友来引用通用属性对我来说似乎不够优雅和脆弱。如果子类重新实现这些方法,则必须适应此行为。我宁愿让用户觉得只有一个带有命名属性的基类可以天真地访问。

实际上,我可以想到一个看似合理的用例。假设您需要一个赋予特殊属性的mixin类和一些操纵或依赖此属性的密切相关的方法。用户可能希望为不同的类命名此特殊属性(以匹配现实问题域中的名称或避免名称冲突),同时重用基础行为。

4 个答案:

答案 0 :(得分:4)

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

使用通用属性名称定义泛型类。然后在每个子类中遵循http://docs.python.org/reference/datamodel.html#customizing-attribute-access中的建议,使属性看起来像外部一样,无论你想要它调用它。

您对自己所做的事情的描述感觉它对我有“代码味道”,我建议您仔细检查您的设计,看看这是否真的是您想要做的。但你可以按照我的建议使用它。

答案 1 :(得分:0)

您还可以创建一个包含所有常见内容的超类,然后创建具有特定属性的子类。

甚至:

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'

答案 2 :(得分:0)

您是否考虑过不会过度复杂化而只创建一个类? (因为它们无论如何都是相同的)

class FoodClass(object):
    def __init__(self, foodname, arg):
        self.attrs = {foodname: arg}
        self.foodname = foodname

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

如果你想要一些不错的构造函数,只需单独创建它们:

def make_eggs(arg):
    return FoodClass('eggs', arg)

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

答案 3 :(得分:0)

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