我需要在Python中动态创建类的实例。基本上,我使用load_module和inspect模块将类导入并将其加载到类对象中,但是我不知道如何创建该类对象的实例。
请帮忙!
我需要在Python中动态创建类的实例。基本上,我使用load_module和inspect模块将类导入并将其加载到类对象中,但是我不知道如何创建该类对象的实例。
请帮忙!
Answers:
我想出了我要带到此页面的问题的答案。由于实际上没有人提出我的问题的答案,因此我认为应该发表它。
class k:
pass
a = k()
k2 = a.__class__
a2 = k2()
此时,a和a2都是同一类(k类)的实例。
a3 = k2(7)
k2 = a.__class__
和之间有什么区别k2 = k
?
k2
是对象类型,在这种情况下为a
(a.__class
)的类型,k2()
创建一个独立于的类型的对象的新实例a
。k2 = k
只会创建对同一实例的新引用。
class
对象,k2 = type(a)
然后调用类对象a2 = k2()
。从根本上说是一样的,但是您不必用那些难看的双下划线把代码乱七八糟……也可能更具可移植性
只需使用以下三个参数调用内置的“类型”即可:
ClassName = type("ClassName", (Base1, Base2,...), classdictionary)
如下面的评论中所述更新,这根本不是这个问题的答案。我将不删除它,因为有一些人来到这里尝试动态创建类的提示-这就是上面的代码所做的。
要创建一个类的对象,也要有一个引用,就像接受的答案中所提到的,只需调用该类即可:
instance = ClassObject()
因此,实例化的机制是:
Python不使用new
某些语言使用的关键字-相反,它的数据模型解释了使用与任何其他可调用对象相同的语法调用类时用于创建类实例的机制:
__call__
调用其类的方法(在类的情况下,其类为“元类”-通常是内置的type
)。此调用的正常行为是__new__
在要实例化的类上调用(伪)静态方法,然后调用__init__
。该__new__
方法是负责分配存储器和例如,通常是由完成__new__
的object
,其是类层次的根。
因此调用ClassObject()
所调用ClassObject.__class__.call()
(通常会type.__call__
)这个__call__
方法会收到ClassObject本身作为第一个参数-一个纯Python实现是这样的:(CPython的版本是当然的,在C做的,有很多的额外代码cornercases和优化)
class type:
...
def __call__(cls, *args, **kw):
constructor = getattr(cls, "__new__")
instance = constructor(cls) if constructor is object.__new__ else constructor(cls, *args, **kw)
instance.__init__(cls, *args, **kw)
return instance
(我不记得在文档上看到了将多余参数压制到根__new__
并将其传递给其他类的确切理由(或机制)-但这是“在现实生活中”发生的情况-如果object.__new__
使用任何额外参数调用它引发类型错误-但是,任何自定义实现__new__
都会正常获得额外的参数)
Child
假设Parent
已经存在,这就是您可以动态创建代码中命名的类的方法,即使您没有显式Parent
类,也可以使用object
...
下面的代码定义__init__()
然后将其与该类相关联。
>>> child_name = "Child"
>>> child_parents = (Parent,)
>>> child body = """
def __init__(self, arg1):
# Initialization for the Child class
self.foo = do_something(arg1)
"""
>>> child_dict = {}
>>> exec(child_body, globals(), child_dict)
>>> childobj = type(child_name, child_parents, child_dict)
>>> childobj.__name__
'Child'
>>> childobj.__bases__
(<type 'object'>,)
>>> # Instantiating the new Child object...
>>> childinst = childobj()
>>> childinst
<__main__.Child object at 0x1c91710>
>>>
如果您的模块带有要导入的类,则可以这样进行。
module = __import__(filename)
instance = module.MyClass()
如果您不知道该类的名称,则可以遍历模块中可用的类。
import inspect
module = __import__(filename)
for c in module.__dict__.values():
if inspect.isclass(c):
# You may need do some additional checking to ensure
# it's the class you want
instance = c()
instance = Class()
...