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
添加到 Modified
的 bases
将使其生效:
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()
=] 方法,Modified
是 Original
的子 class(除非您在 Modified
class 中还修改了 __init__
方法"copied").
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__()
,是在编译时确定的。
我正在尝试以编程方式复制然后修改 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
添加到 Modified
的 bases
将使其生效:
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()
=] 方法,Modified
是 Original
的子 class(除非您在 Modified
class 中还修改了 __init__
方法"copied").
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__()
,是在编译时确定的。