Python 3 超级和元编程

Python 3 super and metaprogramming

我正在尝试以编程方式复制然后修改 class,但我 运行 遇到 python 3 的魔法超级问题,例如以下

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 必须是 type

的实例或子类型

所以我想知道,有什么方法可以帮助 super() 在通过 type() 创建的 class 中找到正确的 __class__ 单元格?

注意我更正了这个答案中Original的拼写


问题似乎是,当您的 Modified 对象被实例化并调用 super 时,它被调用为:super(Original, self) 因为这些是 super。由于 Original 不是 Modified 的超级 class(检查 isinstance(m, Original)),python 不允许您以这种方式调用 super

以下代码与您的类似,但更能说明问题。

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 添加到 Modifiedbases 将使其生效:

Modified = type(Original.__name__, (Original,) + Original.__bases__, dict(Original.__dict__))

编辑:

根据评论,上述建议可以简化,因为 Original 中包含的所有方法都将包含在 Modified 中,而无需在 [=29] 中传递 dict =] 电话:

Modified = type(Original.__name__, (Original,), {})

更进一步,如果您不想 Modified 成为 Original 的子 class,您可以简单地使 Modified Original 的副本,然后像在示例中一样添加属性:

from copy import deepcopy
Modified = deepcopy(Original)
Modified.f = lambda self: print("f")

m = Modified()

查看 this answer,您似乎无法使用 deepcopy 来复制 classes,并且假设您在 [=36] 中调用了 super() =] 方法,ModifiedOriginal 的子 class(除非您在 Modified class 中还修改了 __init__ 方法"copied").

根据the documentation,

Also note that, aside from the zero argument form, super() is not limited to use inside methods. The two argument form specifies the arguments exactly and makes the appropriate references. The zero argument form only works inside a class definition, as the compiler fills in the necessary details to correctly retrieve the class being defined, as well as accessing the current instance for ordinary methods.

所以,代码中的super()等价于super(Orginal, self).__init__(),是在编译时确定的。