给定一个字符串作为Python函数的用户输入,如果当前定义的命名空间中有一个具有该名称的类,则希望从中获得一个类对象。本质上,我想实现一个函数,它将产生这样的结果:
class Foo:
pass
str_to_class("Foo")
==> <class __main__.Foo at 0x69ba0>
这有可能吗?
给定一个字符串作为Python函数的用户输入,如果当前定义的命名空间中有一个具有该名称的类,则希望从中获得一个类对象。本质上,我想实现一个函数,它将产生这样的结果:
class Foo:
pass
str_to_class("Foo")
==> <class __main__.Foo at 0x69ba0>
这有可能吗?
当前回答
你可以这样做:
globals()[class_name]
其他回答
您需要类Baz,它位于模块foo.bar中。在Python 2.7中, 你想要使用importlib.import_module(),因为这将使过渡到Python 3更容易:
import importlib
def class_for_name(module_name, class_name):
# load the module, will raise ImportError if module cannot be loaded
m = importlib.import_module(module_name)
# get the class, will raise AttributeError if class cannot be found
c = getattr(m, class_name)
return c
使用Python < 2.7:
def class_for_name(module_name, class_name):
# load the module, will raise ImportError if module cannot be loaded
m = __import__(module_name, globals(), locals(), class_name)
# get the class, will raise AttributeError if class cannot be found
c = getattr(m, class_name)
return c
Use:
loaded_class = class_for_name('foo.bar', 'Baz')
你可以这样做:
globals()[class_name]
import sys
import types
def str_to_class(field):
try:
identifier = getattr(sys.modules[__name__], field)
except AttributeError:
raise NameError("%s doesn't exist." % field)
if isinstance(identifier, (types.ClassType, types.TypeType)):
return identifier
raise TypeError("%s is not a class." % field)
这可以准确地处理旧样式和新样式的类。
警告:eval()可用于执行任意Python代码。永远不要对不受信任的字符串使用eval()。(请参阅Python的eval()对不受信任字符串的安全性?)
这似乎是最简单的。
>>> class Foo(object):
... pass
...
>>> eval("Foo")
<class '__main__.Foo'>
我看了django是怎么处理的
django.utils。Module_loading有这个
def import_string(dotted_path):
"""
Import a dotted module path and return the attribute/class designated by the
last name in the path. Raise ImportError if the import failed.
"""
try:
module_path, class_name = dotted_path.rsplit('.', 1)
except ValueError:
msg = "%s doesn't look like a module path" % dotted_path
six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])
module = import_module(module_path)
try:
return getattr(module, class_name)
except AttributeError:
msg = 'Module "%s" does not define a "%s" attribute/class' % (
module_path, class_name)
six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])
你可以像import_string("module_path.to.all.the.way.to.your_class")一样使用它。