Python 3 超级和元编程 [英] Python 3 super and metaprogramming
问题描述
我正在尝试以编程方式复制然后修改一个类,但是我遇到了 python 3 的魔术超级问题,例如以下
I'm trying to duplicate and then modify a class programmatically but I'm running into problems with python 3's magic super for example the following
class Base():
def __init__(self):
print("Base init")
class Orginal(Base):
def __init__(self):
super().__init__()
print("Orginal init")
Modified = type(Orginal.__name__, Orginal.__bases__, dict(Orginal.__dict__))
Modified.f = lambda self: print("f")
m = Modified()
加注
TypeError: super(type, obj): obj must be an instance or subtype of type
TypeError: super(type, obj): obj must be an instance or subtype of type
所以我想知道,有什么办法可以帮助 super() 在通过 type() 创建的类中找到正确的 __class__ 单元格吗?
So I'm wondering, is there someway I can help super() find the right __class__ cell in a class created through type()?
推荐答案
注意:我更正了这个答案中Original
的拼写
问题似乎在于,当您的 Modified
对象被实例化并且 super
被调用时,它的调用方式如下:super(Original, self)
因为这些是 super
的默认参数.由于 Original
不是 Modified
的超类(检查 isinstance(m, Original)
),python 不允许您调用 super
那样.
It appears that the problem is that when your Modified
object is being instantiated and super
is called, its being called like: super(Original, self)
since those are the default arguments for super
. Since Original
is not a superclass of Modified
(check isinstance(m, Original)
), python is not allowing you to call super
in that way.
以下代码与您的代码类似,但更好地说明了问题.
The following code does something similar to yours but better illustrates the problem.
class Base():
def __init__(self):
print("Base init")
class Original(Base):
def __init__(self):
super().__init__()
print("Orginal init")
class Modified(Base):
def __init__(self):
super(Original, self).__init__() # illegal
Modified.__name__ == Original.__name__
m = Modified() # raises same Exception that your your code does
将 Original
添加到 Modified
的 bases
将使其工作:
Adding Original
to the bases
of Modified
will make it work:
Modified = type(Original.__name__, (Original,) + Original.__bases__, dict(Original.__dict__))
<小时>
编辑:
根据评论,上述建议可以简化,因为 Original
中包含的所有方法都将包含在 Modified
中,而无需传递 dict
在 type
调用中:
Per the comments, the above suggestion can be simplified since all the methods contained within Original
will be included in Modified
without needing to pass the dict
in the type
call:
Modified = type(Original.__name__, (Original,), {})
更进一步,如果您不希望 Modified
成为 Original
的子类,您可以简单地制作 Modified
Original
的副本,然后添加与您在示例中相同的属性:
and going one step further, if you don't want Modified
to be a subclass of Original
, you could simply make Modified
a copy of Original
and then add attributes the same as you do in your example:
from copy import deepcopy
Modified = deepcopy(Original)
Modified.f = lambda self: print("f")
m = Modified()
看这个答案,看来你不能用deepcopy
来复制类,并且假设您在 Original.__init__
方法中有 super()
调用,Modified
是 Original
的子类> (除非您在复制"后还修改了 Modified
类中的 __init__
方法).
Looking at this answer, it appears that you cannot use deepcopy
to copy classes, and given that you have that super()
call in your Original.__init__
method, Modified
be a subclass of Original
(unless you also modify the __init__
method in your Modified
class after it's been "copied").
这篇关于Python 3 超级和元编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!