从字符串列表中构建类名

时间:2014-08-04 14:18:04

标签: python

我在Frame中继承LabelTkinter以自动.pack()他们(这只是一个用法示例,我的问题与Tkinter没有严格关系)。除标签外,两个类的定义相同:

class Frame(tk.Frame):
    def __init__(self, parent, **kwargs):
        objparams, packparams = dispatch_parameters(self, **kwargs)
        tk.Frame.__init__(self, parent, objparams)
        self.pack(packparams)

class Label(tk.Label):
    def __init__(self, parent, **kwargs):
        objparams, packparams = dispatch_parameters(self, **kwargs)
        tk.Label.__init__(self, parent, objparams)
        self.pack(packparams)

为了不为这两个类重复相同的代码,我想知道如何通过改变“标签”来重用它。我知道上面的“Frame”意味着类中的不同事物(一个类名,一个实际的类,......)所以我试图理解是否正确看待某些事情(这是伪代码,试图解释我的观点)

for classname in ["Frame", "Label"]:
  class <<classname>>(tk.<<classname>>):
    def __init__(self, parent, **kwargs):
        objparams, packparams = dispatch_parameters(self, **kwargs)
        tk.<<classname>>.__init__(self, parent, objparams)
        self.pack(packparams)

这种代码重用案例是否存在pythonic方法?或者我应该坚持一个接一个地定义类,即使代码非常相似?

注1:我认为这个问题与another one, but for objective-c

非常相似

注2:我故意省略tkinter标签,因为我给出的例子只是一般情况的具体实例

1 个答案:

答案 0 :(得分:1)

您可以使用type() function动态创建类:

def class_factory(classname):
    base_class = getattr(tk, classname)

    def __init__(self, parent, **kwargs):
        objparams, packparams = dispatch_parameters(self, **kwargs)
        base_class.__init__(self, parent, objparams)
        self.pack(packparams)

    return type(classname, (base_class, object), {'__init__': __init__})

for classname in ["Frame", "Label"]:
    globals()[classname] = class_factory(classname)

当给出3个参数时,type()函数会从中生成一个类。第一个参数是名称,第二个参数是基类的元组,第三个参数是表示类体的映射。

此处需要object基础,以便使用Tkinter模块中的旧式类。

另一种选择是将class语句的范围放在函数中:

def class_factory(classname):
    base_class = getattr(tk, classname)

    class CustomClass(base_class):
        def __init__(self, parent, **kwargs):
            objparams, packparams = dispatch_parameters(self, **kwargs)
            base_class.__init__(self, parent, objparams)
            self.pack(packparams)

    CustomClass.__name__ = classname
    return CustomClass

在这里,我们不必混合使用object基类。