我需要接受一个字符串参数,并在Python中创建一个以该字符串命名的类的对象。在Java中,我将使用Class.forName().newInstance()
。 Python中是否有等效项?
感谢您的回复。回答那些想知道我在做什么的人:我想使用命令行参数作为类名,并实例化它。我实际上是在Jython编程并实例化Java类,因此是问题的Java实质。 getattr()
效果很好。非常感谢。
[Python中的反射比Java中的反射更容易,而且更灵活。
我建议阅读此tutorial
[我不知道,没有直接函数使用完全限定的类名并返回该类,但是您拥有构建它所需的所有组件,并且可以将它们连接在一起。
但是有一点建议:当您使用python时,请勿尝试以Java风格进行编程。
如果您可以解释您要做什么,也许我们可以帮助您找到更Python化的方式。
这里有一个功能可以满足您的需求:
def get_class( kls ):
parts = kls.split('.')
module = ".".join(parts[:-1])
m = __import__( module )
for comp in parts[1:]:
m = getattr(m, comp)
return m
您可以像使用类本身一样使用此函数的返回值。
这是一个用法示例:
>>> D = get_class("datetime.datetime")
>>> D
<type 'datetime.datetime'>
>>> D.now()
datetime.datetime(2009, 1, 17, 2, 15, 58, 883000)
>>> a = D( 2010, 4, 22 )
>>> a
datetime.datetime(2010, 4, 22, 0, 0)
>>>
这是如何工作的?
我们正在使用__import__
导入保存该类的模块,这要求我们首先从完全限定的名称中提取模块名称。然后我们导入模块:
m = __import__( module )
在这种情况下,m
仅指顶级模块,>>
例如,如果您的班级住在foo.baz
模块中,那么m
将是模块foo
我们可以使用foo.baz
getattr( m, 'baz' )
的引用要从顶层模块进入类,必须在类名的各个部分上递归使用gettatr
例如,如果您的班级名称是foo.baz.bar.Model
,那么我们这样做:
m = __import__( "foo.baz.bar" ) #m is package foo m = getattr( m, "baz" ) #m is package baz m = getattr( m, "bar" ) #m is module bar m = getattr( m, "Model" ) #m is class Model
这是此循环中发生的事情:
for comp in parts[1:]: m = getattr(m, comp)
在循环结束时,
m
将是对该类的引用。这意味着m
实际上是itslef类,您可以例如执行以下操作:
a = m() #instantiate a new instance of the class
b = m( arg1, arg2 ) # pass arguments to the constructor
假设班级在您的范围内:
def import_class_from_string(path):
from importlib import import_module
module_path, _, class_name = path.rpartition('.')
mod = import_module(module_path)
klass = getattr(mod, class_name)
return klass
还有另一个实现。
似乎您正在从中间而不是开始着手。您到底想做什么?查找与给定字符串关联的类是达到目的的一种方法。
这在python标准库中找到,作为unittest.TestLoader.loadTestsFromName。不幸的是,该方法继续进行其他与测试相关的活动,但是,此方法看起来可重复使用。我已经对其进行了编辑,以删除与测试相关的功能:
我需要获取my_package
中所有现有类的对象。因此,我将所有必要的类导入my_package
的__init__.py
。