파이썬 함수에 대한 사용자 입력으로 문자열이 주어지면 현재 정의 된 네임 스페이스에 해당 이름의 클래스가있는 경우 클래스 객체를 가져 오려고합니다. 본질적으로 이러한 종류의 결과를 생성하는 함수에 대한 구현을 원합니다.
class Foo:
pass
str_to_class("Foo")
==> <class __main__.Foo at 0x69ba0>
이것이 가능합니까?
답변
경고 :
eval()
임의의 파이썬 코드를 실행하는 데 사용할 수 있습니다. 신뢰할 수없는 문자열과 함께 사용 해서는 안됩니다eval()
. ( 신뢰할 수없는 문자열에 대한 Python eval ()의 보안? )
가장 간단한 것 같습니다.
>>> class Foo(object):
... pass
...
>>> eval("Foo")
<class '__main__.Foo'>
답변
이것은 작동 할 수 있습니다 :
import sys
def str_to_class(classname):
return getattr(sys.modules[__name__], classname)
답변
당신은 다음과 같은 것을 할 수 있습니다 :
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
파이썬 <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
사용하다:
loaded_class = class_for_name('foo.bar', 'Baz')
답변
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)
이것은 구식과 신식 수업을 정확하게 처리합니다.
답변
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")
답변
예, 당신은 이것을 할 수 있습니다. 클래스가 전역 네임 스페이스에 있다고 가정하면 다음과 같이됩니다.
import types
class Foo:
pass
def str_to_class(s):
if s in globals() and isinstance(globals()[s], types.ClassType):
return globals()[s]
return None
str_to_class('Foo')
==> <class __main__.Foo at 0x340808cc>