python是否等效于Java Class.forName()?

问题描述 投票:88回答:7

我需要接受一个字符串参数,并在Python中创建一个以该字符串命名的类的对象。在Java中,我将使用Class.forName().newInstance()。 Python中是否有等效项?


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

java python class instantiation
7个回答
158
投票

[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

25
投票

假设班级在您的范围内:


11
投票
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

4
投票

还有另一个实现。


3
投票

似乎您正在从中间而不是开始着手。您到底想做什么?查找与给定字符串关联的类是达到目的的一种方法。


1
投票

这在python标准库中找到,作为unittest.TestLoader.loadTestsFromName。不幸的是,该方法继续进行其他与测试相关的活动,但是,此方法看起来可重复使用。我已经对其进行了编辑,以删除与测试相关的功能:


0
投票

我需要获取my_package中所有现有类的对象。因此,我将所有必要的类导入my_package__init__.py

© www.soinside.com 2019 - 2024. All rights reserved.