我正在寻找一种基于传入参数动态“识别”类名并创建其对象的方法。 我尝试的代码给出错误“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)
由于
答案 0 :(得分:-1)
我所做的(例如在我的引擎中Contemplate),是这样的:
所有这些假设该类是动态的,但是从一组特定的可用类开始,示例代码如下:
样本可用类:
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
这个方案可以实现这些目标:
动态文件和模块/类加载,其中classname / file是动态的,但类名可能与filename不对应(在每个模块/类中都有一个通用的__getClass__
函数)
动态类文件可以动态生成(作为源代码)或者预先缓存等等......如果已经可用,则无需(重新)生成。
动态类集是特定的而非临时的,但如果需要,它可以在运行时动态更改和/或放大
答案 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()
这当然不仅限于类,您也可以以相同的方式存储和调用方法。