python 有相当于 Java Class.forName() 的吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/452969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Does python have an equivalent to Java Class.forName()?
提问by Jason
I have the need to take a string argument and create an object of the class named in that string in Python. In Java, I would use Class.forName().newInstance()
. Is there an equivalent in Python?
我需要接受一个字符串参数并在 Python 中创建一个以该字符串命名的类的对象。在 Java 中,我会使用Class.forName().newInstance()
. Python中是否有等价物?
Thanks for the responses. To answer those who want to know what I'm doing: I want to use a command line argument as the class name, and instantiate it. I'm actually programming in Jython and instantiating Java classes, hence the Java-ness of the question. getattr()
works great. Thanks much.
感谢您的回复。回答那些想知道我在做什么的人:我想使用命令行参数作为类名,并将其实例化。我实际上是在 Jython 中编程并实例化 Java 类,因此问题的 Java 性。 getattr()
效果很好。非常感谢。
采纳答案by hasen
Reflection in python is a lot easier and far more flexible than it is in Java.
Python 中的反射比 Java 中的反射要容易得多,也灵活得多。
I recommend reading this tutorial
我建议阅读本教程
There's no direct function (that I know of) which takes a fully qualified class name and returns the class, however you have all the pieces needed to build that, and you can connect them together.
没有直接函数(据我所知)采用完全限定的类名并返回类,但是您拥有构建它所需的所有部分,并且可以将它们连接在一起。
One bit of advice though: don't try to program in Java style when you're in python.
不过有一点建议:当您使用 python 时,不要尝试以 Java 风格进行编程。
If you can explain what is it that you're trying to do, maybe we can help you find a more pythonic way of doing it.
如果你能解释你想要做什么,也许我们可以帮助你找到一种更 Pythonic 的方式来做这件事。
Here's a function that does what you want:
这是一个可以完成您想要的功能的函数:
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
You can use the return value of this function as if it were the class itself.
您可以使用此函数的返回值,就好像它是类本身一样。
Here's a usage example:
这是一个使用示例:
>>> 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)
>>>
How does that work?
这是如何运作的?
We're using __import__
to import the module that holds the class, which required that we first extract the module name from the fully qualified name. Then we import the module:
我们使用__import__
导入包含类的模块,这要求我们首先从完全限定名称中提取模块名称。然后我们导入模块:
m = __import__( module )
In this case, m
will only refer to the top level module,
在这种情况下,m
只会引用顶层模块,
For example, if your class lives in foo.baz
module, then m
will be the module foo
We can easily obtain a reference to foo.baz
using getattr( m, 'baz' )
例如,如果你的类生活在foo.baz
模块,然后m
将模块foo
,我们可以很容易地获得一个参考foo.baz
使用getattr( m, 'baz' )
To get from the top level module to the class, have to recursively use gettatr
on the parts of the class name
要从顶级模块到类,必须递归使用gettatr
类名的部分
Say for example, if you class name is foo.baz.bar.Model
then we do this:
比如说,如果你的类名是,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
This is what's happening in this loop:
这是这个循环中发生的事情:
for comp in parts[1:]:
m = getattr(m, comp)
At the end of the loop, m
will be a reference to the class. This means that m
is actually the class itslef, you can do for instance:
在循环结束时,m
将是对类的引用。这意味着它m
实际上是类 itslef,您可以执行以下操作:
a = m() #instantiate a new instance of the class
b = m( arg1, arg2 ) # pass arguments to the constructor
回答by Cody Brocious
Assuming the class is in your scope:
假设该课程在您的范围内:
globals()['classname'](args, to, constructor)
Otherwise:
除此以外:
getattr(someModule, 'classname')(args, to, constructor)
Edit: Note, you can't give a name like 'foo.bar' to getattr. You'll need to split it by . and call getattr() on each piece left-to-right. This will handle that:
编辑:请注意,您不能为 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)
回答by hasen
It seems you're approaching this from the middle instead of the beginning. What are you really trying to do? Finding the class associated with a given string is a means to an end.
看来你是从中间而不是一开始就接近这个问题。你真正想要做什么?查找与给定字符串关联的类是达到目的的一种手段。
If you clarify your problem, which might require your own mental refactoring, a better solution may present itself.
如果你澄清你的问题,这可能需要你自己的心理重构,一个更好的解决方案可能会出现。
For instance: Are you trying to load a saved object based on its type name and a set of parameters? Python spells this unpickling and you should look at the pickle module. And even though the unpickling process does exactly what you describe, you don't have to worry about how it works internally:
例如:您是否尝试根据类型名称和一组参数加载保存的对象?Python 拼写了这种 unpickling,您应该查看pickle 模块。即使 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))
>>> a.v, b.v
('example', 'example')
>>> a is b
False
回答by grayhemp
Yet another implementation.
又一个实现。
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)
回答by bukzor
This is found in the python standard library, as unittest.TestLoader.loadTestsFromName. Unfortunately the method goes on to do additional test-related activities, but this first ha looks re-usable. I've edited it to remove the test-related functionality:
这可以在 python 标准库中找到,作为 unittest.TestLoader.loadTestsFromName。不幸的是,该方法继续执行其他与测试相关的活动,但这第一个 ha 看起来可重用。我对其进行了编辑以删除与测试相关的功能:
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
回答by 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
Usage
用法
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:
回答by Sushant Chaudhary
I needed to get objects for all existing classes in my_package
. So I import all necessary classes into my_package
's __init__.py
.
我需要为my_package
. 所以我导入所有必需的类到my_package
的__init__.py
。
So my directory structure is like this:
所以我的目录结构是这样的:
/my_package
- __init__.py
- module1.py
- module2.py
- module3.py
And my __init__.py
looks like this:
我的__init__.py
样子是这样的:
from .module1 import ClassA
from .module2 import ClassB
Then I create a function like this:
然后我创建一个这样的函数:
def get_classes_from_module_name(module_name):
return [_cls() for _, _cls in inspect.getmembers(__import__(module_name), inspect.isclass)]
Where module_name = 'my_package'
在哪里 module_name = 'my_package'
inspect doc: https://docs.python.org/3/library/inspect.html#inspect.getmembers
检查文档:https: //docs.python.org/3/library/inspect.html#inspect.getmembers