问题:python是否与Java Class.forName()等效?
我需要使用字符串参数并在Python中创建以该字符串命名的类的对象。在Java中,我会使用Class.forName().newInstance()
。Python中是否有等效的东西?
感谢您的答复。回答那些想知道我在做什么的人:我想使用命令行参数作为类名,并实例化它。我实际上是在Jython编程并实例化Java类,因此是问题的Java实质。 getattr()
效果很好。非常感谢。
回答 0
python中的反射比Java中的反射更容易,更灵活。
我建议阅读本教程
没有直接函数(据我所知)具有完全限定的类名并返回该类,但是您拥有构建该函数所需的所有组件,并且可以将它们连接在一起。
不过,有一点建议:使用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
回答 1
假设该类在您的范围内:
globals()['classname'](args, to, constructor)
除此以外:
getattr(someModule, 'classname')(args, to, constructor)
编辑:注意,您不能给’att.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)
回答 2
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:
回答 3
另一个实现。
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)
回答 4
看来您正在从中间而不是开始着手。您到底想做什么?查找与给定字符串关联的类是达到目的的一种手段。
如果您弄清楚了问题,可能需要您自己进行心理重构,那么可能会发现一个更好的解决方案。
例如:您是否要根据对象的类型名称和一组参数来加载它?Python拼写了这种解开,您应该看一下pickle模块。即使解开流程完全符合您的描述,您也不必担心它在内部如何工作:
>>> 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))
>>> a.v, b.v
('example', 'example')
>>> a is b
False
回答 5
在python标准库中可以找到它,为unittest.TestLoader.loadTestsFromName。不幸的是,该方法继续进行其他与测试有关的活动,但是,此方法看起来可重复使用。我已经对其进行了编辑,以删除与测试相关的功能:
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
回答 6
我需要获取中所有现有类的对象my_package
。因此,我将所有必要的类导入my_package
的__init__.py
。
所以我的目录结构是这样的:
/my_package
- __init__.py
- module1.py
- module2.py
- module3.py
我的__init__.py
样子是这样的:
from .module1 import ClassA
from .module2 import ClassB
然后我创建一个像这样的函数:
def get_classes_from_module_name(module_name):
return [_cls() for _, _cls in inspect.getmembers(__import__(module_name), inspect.isclass)]
哪里 module_name = 'my_package'
检查文档:https : //docs.python.org/3/library/inspect.html#inspect.getmembers