python和java元编程,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()

raises

TypeError: super(type, obj): obj must be an instance or subtype of type

So I'm wondering, is there someway I can help super() find the right __class__ cell in a class created through type()?

解决方案

Note: I corrected the spelling of Original in this answer

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

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

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

Edit:

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,), {})

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()

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").

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值