python 是否有与 Java Class.forName() 等效的函数?

2025-02-20 09:24:00
admin
原创
68
摘要:问题描述:我需要获取一个字符串参数,并在 Python 中创建该字符串命名的类的对象。在 Java 中,我会使用Class.forName().newInstance()。Python 中有等效的吗?谢谢大家的回复。回答那些想知道我在做什么的人:我想使用命令行参数作为类名,并实例化它。我实际上是用 Jytho...

问题描述:

我需要获取一个字符串参数,并在 Python 中创建该字符串命名的类的对象。在 Java 中,我会使用Class.forName().newInstance()。Python 中有等效的吗?


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


解决方案 1:

Python 中的反射比 Java 中的反射容易得多,而且灵活得多。

我建议阅读这个教程(在archive.org上)

没有直接函数(据我所知)采用完全限定的类名并返回该类,但是您拥有构建该类所需的所有部分,并且可以将它们连接在一起。

不过有一条建议:当你使用 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实际上是该类本身,例如,您可以执行以下操作:

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

  

解决方案 2:

假设该课程在你的范围内:

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:

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: 

解决方案 4:

还有另一种实现。

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)

解决方案 5:

看起来您是从中间开始处理这个问题,而不是从头开始。您真正想做什么?查找与给定字符串关联的类是达到目的的一种手段。

如果你澄清了你的问题,这可能需要你自己的心理重构,那么可能会出现更好的解决方案。

例如:您是否尝试根据其类型名称和一组参数加载已保存的对象? 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

解决方案 6:

这可以在 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

解决方案 7:

我需要获取 中所有现有类的对象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

解决方案 8:

这个非常简短的实现适用于我的目的(内置类):

str_name = "str"
class_from_str = eval(str_name + "()".__class__)

在我的测试中,这对模块和一些其他导入的对象不起作用,尽管它在通过导入的类上运行良好from x import y

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3958  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2737  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   74  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   83  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   70  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用