python是否具有与Java Class.forName()相同的function?

我有需要采取一个string参数,并创build在Python中的string中指定类的对象。 在Java中,我会使用Class.forName().newInstance() 。 Python中是否有相当的东西?


感谢您的回应。 要回答那些想知道我在做什么的人:我想使用命令行参数作为类名,并实例化它。 我实际上是用Jython进行编程并实例化Java类,因此问题的Java性。 getattr()很好。 非常感谢。

python中的reflection比Java中的reflection要容易得多,灵活得多。

我build议阅读本教程

有没有直接的函数(我知道),它取得一个完全合格的类名称并返回类,但是你有所有必要的构件,并可以将它们连接在一起。

有一点build议,但不要试图在Java中编程,当你在Python中。

如果你能解释你想要做的是什么,也许我们可以帮助你find一个更加pythonic的方式来做到这一点。

这是一个你想要的function:

 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
我们可以使用getattr( m, 'baz' )轻松获得对foo.baz的引用

为了从顶层模块到类,必须recursion地使用类名部分的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实际上是它的类,例如你可以这样做:

 a = m() #instantiate a new instance of the class b = m( arg1, arg2 ) # pass arguments to the constructor 

假设这个类在你的范围内:

 globals()['classname'](args, to, constructor) 

除此以外:

 getattr(someModule, 'classname')(args, to, constructor) 

编辑:注意,你不能给一个名字像'foo.bar'getattr。 你需要把它分开。 并从左到右每块调用getattr()。 这将处理:

 module, rest = 'foo.bar.baz'.split('.', 1) fooBar = reduce(lambda a, b: getattr(a, b), rest.split('.'), globals()[module]) someVar = fooBar(args, to, 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 

用法

 In [59]: raise import_class_from_string('google.appengine.runtime.apiproxy_errors.DeadlineExceededError')() --------------------------------------------------------------------------- DeadlineExceededError Traceback (most recent call last) <ipython-input-59-b4e59d809b2f> in <module>() ----> 1 raise import_class_from_string('google.appengine.runtime.apiproxy_errors.DeadlineExceededError')() DeadlineExceededError: 

又一个实现。

 def import_class(class_string): """Returns class object specified by a string. Args: class_string: The string representing a class. Raises: ValueError if module part of the class is not specified. """ module_name, _, class_name = class_string.rpartition('.') if module_name == '': raise ValueError('Class name must contain module part.') return getattr( __import__(module_name, globals(), locals(), [class_name], -1), class_name) 

看来你是从中间而不是从头开始的。 你真的想做什么? find与给定string相关的类是达到目的的一种手段。

如果你澄清你的问题,这可能需要你自己的精神重构,一个更好的解决scheme可能会出现。

例如:你是否试图根据types名称和一组参数来加载保存的对象? Python拼出这个unpickling,你应该看看泡菜模块 。 即使取消过程完全按照您描述的内容进行,您不必担心内部如何工作:

 >>> class A(object): ... def __init__(self, v): ... self.v = v ... def __reduce__(self): ... return (self.__class__, (self.v,)) >>> a = A("example") >>> import pickle >>> b = pickle.loads(pickle.dumps(a)) >>> av, bv ('example', 'example') >>> a is b False 

这可以在python标准库中find,如unittest.TestLoader.loadTestsFromName。 不幸的是,这个方法继续进行额外的testing相关的活动,但是这个第一个ha看起来是可重用的。 我已经编辑它来删除testing相关的function:

 def get_object(name): """Retrieve a python object, given its dotted.name.""" parts = name.split('.') parts_copy = parts[:] while parts_copy: try: module = __import__('.'.join(parts_copy)) break except ImportError: del parts_copy[-1] if not parts_copy: raise parts = parts[1:] obj = module for part in parts: parent, obj = obj, getattr(obj, part) return obj