能否成为内置类型的虚拟子类?
在Python中,能不能让自己定义的类型成为内置类型的虚拟子类呢?我希望我的类能被认为是int
的一个子类,但我不想直接这样继承:
class MyInt(int):
'''Do some stuff kind of like an int, but not exactly'''
pass
因为这样一来,我的类就变得基本上不能修改了,无论我想不想。例如,像__iadd__
和__isub__
这些方法就无法使用,因为int
本身没有办法修改自己。我可以从numbers.Integral
继承,但这样一来,当有人调用isinstance(myIntObj, int)
或者issubclass(MyInt, int)
时,结果会是False
。我知道那些使用了ABCMeta元类的类可以用register
方法来注册类作为虚拟基类,而不是真正的继承。那有没有办法对内置类型做类似的事情呢?比如:
registerAsParent(int, MyInt)
我在Python的文档和网上都查过,但还没找到接近我想要的东西。我问的这个问题真的完全不可能吗?
2 个回答
0
其实这部分是可以做到的:确实,numbers.Number
就是这样做的。
你可以注册一个抽象类 MyInt
,然后像这样把它注册为 int
的父类:
from abc import ABCMeta, abstractmethod
from numbers import Integral
class MyInt(metaclass=ABCMeta):
@abstractmethod
def something_that_int_already_implements(self):
...
MyInt.register(Integral) # superclass of int because numbers registered it
assert issubclass(int, MyInt) # works
assert isinstance(0, MyInt) # works
不过,你不能通过这种方式扩展 int
(新的方法不会被复制),只能用它来检查子类和实例。
1
我不太确定你具体想做什么,因为你问的问题其实是不可能的,因为基本类型是不可变的。不过,你可以重写 __iadd__
这些方法,让它返回你想要的类型的结果。注意,我把符号反过来了(用 -
代替了 +
),只是为了增加点戏剧性。
>>> class MyInt(int):
... def __iadd__(self, other):
... return MyInt(self - other)
... def __add__(self, other):
... return MyInt(self - other)
...
>>> i = MyInt(4)
>>> i += 1
>>> type(i)
<class '__main__.MyInt'>
>>> i
3
>>> i + 5
-2
>>> type(i + 5)
<class '__main__.MyInt'>
接下来对其他的魔法方法也做同样的事情,这样你才能有一个“合适”的 int 子类(即使“虚拟”用户可能会期待它们以某种方式工作)。
哦,对了,为了扩展性(就好像这还不够疯狂一样),用 self.__class__
来处理结果。
class MyInt(int):
def __iadd__(self, other):
return self.__class__(self - other)
所以如果我们有另一个子类的话。
>>> class MyOtherInt(MyInt):
... def __iadd__(self, other):
... return self.__class__(self + other)
...
>>> i = MyOtherInt(4)
>>> i += 4
>>> i
8
>>> type(i)
<class '__main__.MyOtherInt'>