【问题标题】:Is it possible to be a virtual subclass of a built in type?是否有可能成为内置类型的虚拟子类?
【发布时间】:2014-09-28 17:38:34
【问题描述】:

是否可以使用户定义类型成为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 文档中还是在网上),但还没有找到任何与我正在寻找的东西相近的东西。我的要求是完全不可能的吗?

【问题讨论】:

    标签: python inheritance subclass abc


    【解决方案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'>
    

    【讨论】:

    • 好的,是的。我认为这对我来说很有意义。基本上__iadd__ 做了普通int 做的事情;执行操作,然后将i 指向的MyInt 对象替换为新的MyInt 对象。无论出于何种原因,我已经意识到修改对象至关重要。但是返回一个新副本有效地做同样的事情。从实际的角度来看,这应该可以正常工作。不过,从纯理论的角度来看,我仍然有兴趣看看是否有人知道一种方法来使用户类型成为内置类型的“虚拟”子类,不可变或不可变。
    • iadd 不会替换任何东西 - 它只是计算并返回一个新对象。其余的代码进行替换。请记住,如果我们在 python 中执行 a += b,则 a 和 b 只是对整数对象的引用。
    • 这就是我所说的替换。而不是突变self,然后返回self(这是我最初希望做的,以及人们对方法调用__iadd__的期望),metatoaster的答案是返回一个新对象,因此对象@ 987654337@ 指向的对象被替换为新对象(尽管类型相同)。如果我不清楚,我很抱歉。
    • 根本问题是ints are immutable in python,所以你所问的在Python中没有意义/不可能。
    • @eestrada 实际上有一种方法,但绝对愚蠢并且可能会破坏 - 使用MyInt 的内部属性,更新__init__ 来设置它(并调用int.__init__ 以实现兼容性)并实施所有操作(以及__str____repr__),以便您可以模拟“就地”突变,但这在不必要的工作范围内很好。问问自己为什么你要这样做,这对于你想要达到的目标是否实用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 2013-07-27
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    相关资源
    最近更新 更多