Python 3 超级和元编程 [英] Python 3 super and metaprogramming

查看:34
本文介绍了Python 3 超级和元编程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试以编程方式复制然后修改一个类,但是我遇到了 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 添加到 Modifiedbases 将使其工作:

Adding Original to the bases of Modified will make it work:

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

<小时>

编辑:

根据评论,上述建议可以简化,因为 Original 中包含的所有方法都将包含在 Modified 中,而无需传递 dicttype 调用中:

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() 调用,ModifiedOriginal 的子类> (除非您在复制"后还修改了 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆