如何动态地向类添加属性?

时间:2012-01-10 15:50:24

标签: python

我有很多类似的课程,它们都包含自己的课程 类属性:

class MyClass1(): 
    Context = ClassId1+"CONTEXTSTR"
    SubContext = ClassId1+"SUBCONTEXTSTR"
    UpVal = ClassID+"UPVAL"
    DoenVal = ClassID1+"DOWNVAL"
class MyClass2(): 
    Context = ClassId2+"CONTEXTSTR"
    SubContext = ClassId2+"SUBCONTEXTSTR"
    UpVal = ClassID2+"UPVAL"
    DoenVal = ClassID2+"DOWNVAL"
...

但所有这些很快变得烦人,并且需要大量代码重复(容易出错)。

我希望能够操纵一种class_variable并执行以下操作:

class MyClass1():
    self_cls.MakeParameters(ClassId1)

如果我可以使用继承并将参数传递给类来执行以下操作,那就更好了。

ClassID1 = "test01"    

class MyClass1(BaseClass,<ClassID1>):
    pass

print MyClass1.CONTEXT

获取输出“test01CONTEXTSTR”的代码。 如何根据给定参数的给定“模板”设置类的参数?

2 个答案:

答案 0 :(得分:2)

>>> class MyClass:
    def __init__(self, classid):
        self.context = "%s%s" % (classid, "CONTEXTSTR")


>>> somevar = MyClass("someid")
>>> print somevar.context
someidCONTEXTSTR
>>> 

现在,如果你想继承一个类,那就有点不同了。从上面继续:

>>> class NewClass(MyClass):
    def __init__(self, classid, secondid):
        MyClass.__init__(self, classid)
        self.secondcontext = "%s_%s" % (secondid, "SECONDCONTEXT")


>>> secondvar = NewClass("someid", "someotherid")
>>> secondvar.context
'someidCONTEXTSTR'
>>> secondvar.secondcontext
'someotherid_SECONDCONTEXT'
>>> 

要自动设置上下文(我认为你问的是什么?),请使用关键字参数:

>>> class NewClass(MyClass):
    def __init__(self, newclassid="newclassid", myclassid="myclassid"):
        MyClass.__init__(self, myclassid)
        self.newcontext = "%s%s" % (newclassid, " new context")


>>> NewClass().context
'myclassidCONTEXTSTR'
>>> NewClass().newcontext
'newclassid new context'
>>> NewClass(newclassid="only set this ones id").context
'myclassidCONTEXTSTR'
>>> NewClass(newclassid="only set this ones id").newcontext
'only set this ones id new context'
>>> 

这里我没有分配类,我只是调用它(因此括号),关键字为我填充了它。

我认为这就是你的意思?

您还可以将其设置为MyClass的关键字,如果NewClass未设置变量,则会自动分配。我不认为你需要一个代码示例,但问你是否这样做。

我认为这就是你所追求的,如果不是你,你需要澄清一点对不起。

答案 1 :(得分:2)

当然,您可以手动将属性添加到类中:

def addToClass(cls, ClassId):
    cls.Context = ClassId1+"CONTEXTSTR"
    cls.SubContext = ClassId1+"SUBCONTEXTSTR"
    cls.UpVal = ClassID+"UPVAL"
    cls.DoenVal = ClassID1+"DOWNVAL"

class NewClass(MyClass):
    ...

用法:

addToClass(NewClass, "someid")

但如果您认为这仍然是“手动”的,并且您希望像Python这样优秀的语言应该提供更多更好的语言,那么您是对的:元类

使用元类

您可以使用元类实现想要的行为(如果您不知道我在说什么,我建议您阅读本期中发布的最佳答案:What is a metaclass in Python?

编写Metaclass工厂方法:

def getMetaClass(classId):
    class MyMetaClass(type):
        def __new__(cls, name, bases, dct):
            dct["Context"] =  "%sCONTEXTSTR" % classId
            dct["SubContext"] = "%sSUBCONTEXTSTR" % classId
            dct["UpVal"] = "%sUPVAL" % classId
            dct["DownVal"] = "%sDOWNVAL" % classId
            return super(MyMetaClass, cls).__new__(cls, name, bases, dct)
    return MyMetaClass

根据您的元类定义一个类:

class MyClass1():
    __metaclass__ = getMetaClass("test01")

使用你的班级:

>>> A.Context
'test01CONTEXTSTR'

更新:如果您不喜欢在每个课程中都使用此__metaclass__,则可以将其隐藏在这样的超类中(Anders评论中提出):

元类:

class MyMetaClass(type):
    def __new__(cls, name, bases, dct):
        classId = dct.get("CLASSID", "noClassId")
        dct["Context"] =  "%sCONTEXTSTR" % classId
        dct["SubContext"] = "%sSUBCONTEXTSTR" % classId
        dct["UpVal"] = "%sUPVAL" % classId
        dct["DownVal"] = "%sDOWNVAL" % classId
        return super(MyMetaClass, cls).__new__(cls, name, bases, dct)

隐藏元逻辑的类:

class AutoContext:
    __metaclass__ = getMetaClass()

用法:

class MyClass1(AutoContext):
    CLASSID = "test01"