Python:如何动态创建类名

时间:2015-08-18 13:18:20

标签: python-2.7

我正在寻找一种基于传入参数动态“识别”类名并创建其对象的方法。 我尝试的代码给出错误“TypeError:'str'对象不可调用”。 有关如何实现这一目标的任何建议吗?

class interfaceMsg:
    def __init__(self):
        #Do some initializations


    def updateDB(self, cell_index, xml_msg):
        #Do something general


class interfaceMsg_myMsg(interfaceMsg):
    def __init__(self):
        interfaceMsg.__init__(self)
        #Do some specific initializations


class interfaceMsg_yourMsg(interfaceMsg):
    def __init__(self):
        interfaceMsg.__init__(self)
        #Do some special initializations

    def updateDB(self, cell_index, xml_msg):
        #Do something special



##and so on several derived classes



def doUpdateDB(cell_index, xml_msg):
    # I basically want to create an object on the fly and call its updateDB function

    #Create the class name correspoding to this message
    class_name = "interfaceMsg_" + xml_msg.attrib["showname"]

    #class_name becomes interfaceMsg_myMsg or interfaceMsg_yourMsg or interfaceMsg_xyzMsg

    #This gives TypeError: 'str' object is not callable
    obj = class_name()

    obj.updateDB(cell_index, xml_msg)

由于

2 个答案:

答案 0 :(得分:-1)

我所做的(例如在我的引擎中Contemplate),是这样的:

  1. 在子文件夹中提供了一组类
  2. dynamicaly导入相应的类文件
  3. 获取班级的实例
  4. 所有这些假设该类是动态的,但是从一组特定的可用类开始,示例代码如下:

    样本可用类:

    def __getClass__():
    
        class AClass:
    
            # constructor
    
            def __init__(self):
                pass
    
        return AClass
    
    
    
    # allow to 'import *'  from this file as a module
    
    __all__ = ['__getClass__']
    

    示例动态类加载:

    def include( filename, classname, doReload=False ):
        # http://www.php2python.com/wiki/function.include/
        # http://docs.python.org/dev/3.0/whatsnew/3.0.html
        # http://stackoverflow.com/questions/4821104/python-dynamic-instantiation-from-string-name-of-a-class-in-dynamically-imported
    
        #_locals_ = {'Contemplate': Contemplate}
        #_globals_ = {'Contemplate': Contemplate}
        #if 'execfile' in globals():
        #    # Python 2.x
        #    execfile(filename, _globals_, _locals_)
        #    return _locals_[classname]
        #else:
        #    # Python 3.x
        #    exec(Contemplate.read(filename), _globals_, _locals_)
        #    return _locals_[classname]
    
        # http://docs.python.org/2/library/imp.html
        # http://docs.python.org/2/library/functions.html#__import__
        # http://docs.python.org/3/library/functions.html#__import__
        # http://stackoverflow.com/questions/301134/dynamic-module-import-in-python
        # http://stackoverflow.com/questions/11108628/python-dynamic-from-import
        # also: http://code.activestate.com/recipes/473888-lazy-module-imports/
        # using import instead of execfile, usually takes advantage of Python cached compiled code
    
        global _G
        getClass = None
        directory = _G.cacheDir
        # add the dynamic import path to sys
        os.sys.path.append(directory)
        currentcwd = os.getcwd()
        os.chdir(directory)   # change working directory so we know import will work
    
        if os.path.exists(filename):
    
            modname = filename[:-3]  # remove .py extension
            mod = __import__(modname)
            if doReload: reload(mod) # Might be out of date
            # a trick in-order to pass the Contemplate super-class in a cross-module way
            getClass = getattr( mod, '__getClass__' )
    
        # restore current dir
        os.chdir(currentcwd)
        # remove the dynamic import path from sys
        del os.sys.path[-1]
    
        # return the Class if found
        if getClass:  return getClass()
        return None
    

    这个方案可以实现这些目标:

    1. 动态文件和模块/类加载,其中classname / file是动态的,但类名可能与filename不对应(在每个模块/类中都有一个通用的__getClass__函数)

    2. 动态类文件可以动态生成(作为源代码)或者预先缓存等等......如果已经可用,则无需(重新)生成。

    3. 动态类集是特定的而非临时的,但如果需要,它可以在运行时动态更改和/或放大

答案 1 :(得分:-1)

您可能正在寻找globals,它是所有全局变量的字典(包括顶级类和导入):

from yourClasses import ClassA, ClassC

class ClassB(object): pass

def instantiate(className):
    cls = globals()[className] #find the class in the globals dict
    instance = cls()
    return instance

a_instance = instantiate("ClassA")

import random
random_instance = instantiate("Class"+random.choice("ABC"))

或者,建立自己的类词典 - 这将是一个更清晰的选择,尤其是在处理用户输入时。

myClasses = {"A": ClassA, "B": ClassB, "SomethingElseEntirely": ClassC}
clsName = raw_input("")
cls = myClasses[clsName]
instance = cls()

这当然不仅限于类,您也可以以相同的方式存储和调用方法。