Does python have an equivalent to Java Class.forName()?
我需要一个字符串参数,并在python中创建一个在该字符串中命名的类的对象。在爪哇,我会使用
感谢您的回复。要回答那些想知道我在做什么的人:我想使用命令行参数作为类名,并实例化它。我实际上是在Jython编程和实例化Java类,因此问题的Java性。江户十一〔一〕行得很好。非常感谢。
在Python中的反射比Java更容易和更灵活。
我建议阅读本教程
没有直接函数(我知道)接受完全限定的类名并返回类,但是您拥有构建它所需的所有部分,并且可以将它们连接在一起。
不过有一点建议:当你在Python中时,不要尝试用Java风格编程。
如果你能解释一下你想做什么,也许我们可以帮助你找到一种更为Python式的方法。
这里有一个函数可以满足您的需要:
1 2 3 4 5 6 7 | 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 |
。
您可以将此函数的返回值用作类本身。
下面是一个使用示例:
1 2 3 4 5 6 7 8 9 | >>> 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) >>> |
这是怎么回事?
我们正在使用
1 | m = __import__( module ) |
。
在这种情况下,
例如,如果您的类位于
为了从顶层模块到类,必须递归地在类名的各个部分使用
例如,如果您的类名是
1 2 3 4 | 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 |
。
这就是在这个循环中发生的事情:
1 2 | for comp in parts[1:]: m = getattr(m, comp) |
在循环结束时,
1 2 | a = m() #instantiate a new instance of the class b = m( arg1, arg2 ) # pass arguments to the constructor |
。
假设类在您的范围内:
1 | globals()['classname'](args, to, constructor) |
否则:
1 | getattr(someModule, 'classname')(args, to, constructor) |
号
编辑:注意,你不能给getattr起"foo.bar"这样的名字。你得把它分开。并对每一块从左到右调用getattr()。这将处理以下问题:
1 2 3 | module, rest = 'foo.bar.baz'.split('.', 1) fooBar = reduce(lambda a, b: getattr(a, b), rest.split('.'), globals()[module]) someVar = fooBar(args, to, constructor) |
1 2 3 4 5 6 | 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 |
号用法
1 2 3 4 5 6 7 | 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: |
号
还有一个实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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) |
。
似乎你是从中间开始而不是从开始。你到底想做什么?查找与给定字符串关联的类是达到目的的一种方法。
如果你澄清你的问题,这可能需要你自己的精神重构,一个更好的解决方案可能会出现。
例如:您是否试图根据保存的对象的类型名和一组参数加载该对象?python会拼写这个unpickling,您应该查看pickle模块。而且,即使解压过程完全按照您的描述进行,您也不必担心它在内部如何工作:
1 2 3 4 5 6 7 8 9 10 11 12 | >>> 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 |
这可以在python标准库中找到,作为unittest.testloader.loadtestsfromname。不幸的是,该方法继续执行其他与测试相关的活动,但第一个HA看起来是可重用的。我已编辑它以删除与测试相关的功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
号