python是否有与Java Class.forName()等效的python?

2022-08-31 09:45:47

我需要取一个字符串参数,并在Python中创建该字符串中命名的类的对象。在Java中,我会使用.Python中有等效的吗?Class.forName().newInstance()


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


答案 1

Python中的反射比Java中的反射要容易得多,也灵活得多。

我建议阅读本教程

没有直接函数(据我所知)采用完全限定的类名并返回类,但是您拥有构建该类所需的所有部分,并且可以将它们连接在一起。

不过有一点建议:当你在python中时,不要尝试以Java风格编程。

如果你能解释你试图做什么,也许我们可以帮助你找到一种更pythonic的方式。

下面是一个函数,可以执行所需的操作:

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.bazmfoofoo.bazgetattr( 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)    

在循环结束时,将是对类的引用。这意味着这实际上是类itslef,你可以这样做,例如:mm

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

答案 2

假设该类在您的范围内:

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

否则:

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

编辑:请注意,您不能为getattr提供“foo.bar”之类的名称。您需要将其拆分为 。并在每个片段上从左到右调用 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)