当前位置:  开发笔记 > 编程语言 > 正文

python是否具有Java Class.forName()的等价物?

如何解决《python是否具有JavaClass.forName()的等价物?》经验,为你挑选了3个好方法。

我需要获取一个字符串参数,并在Python中创建该字符串中指定的类的对象.在Java中,我会使用Class.forName().newInstance().Python中有相应的东西吗?


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



1> hasen..:

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

>>> 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实际上是它的classlef,你可以这样做:

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


是的,这就是`__import__`的存在.像Django这样做模块加载魔法的项目一直使用它.很好的答案.
`get_class = lambda name:reduce(getattr,name.split('.')[1:],_ _ import {_(name.partition('.')[0]))`.虽然'object.from_name'可能是一个更好的名字.示例:get_class('decimal.Decimal'),get_class(module_name).
Exec是_extremely_危险的.通过动态覆盖范围内的名称并轻松打开罗德岛大小的安全漏洞,可以轻松拍摄自己.

2> Cody Brociou..:

假设课程在您的范围内:

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)



3> Pat..:
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)
 in ()
----> 1 raise import_class_from_string('google.appengine.runtime.apiproxy_errors.DeadlineExceededError')()

DeadlineExceededError: 

推荐阅读
个性2402852463
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有