类继承 - 是否可以将所有继承的方法转换为子类类型?

问题描述 投票:1回答:1

假设我想创建自己的现有类版本。我们选择内置的float类。在这个例子中,我将创建一个像类一样的浮点数,当除以零时不会引发错误,而是返回字符串'inf'(请记住这只是一个例子。避免除零错误不是这个的主要观点题)。

class myfloat(float):
    def __truediv__(self, b):
        if b == 0:
            return 'inf'
        else:
            return myfloat(self.__float__() / b)

当除法与int或float耦合时,它也可以工作。

In[88]: a = myfloat(10)
In[89]: a / 2
Out[89]: 5.0
In[90]: a / 0
Out[90]: 'inf'

但是,由于float类的继承,当我进行任何其他操作(即方法)时,结果将是一个浮点数。例如:

In[92]: b = myfloat(20)
In[93]: (a + b) / 0
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-6-f769cd843514> in <module>()
----> 1 (a + b) / 0

ZeroDivisionError: float division by zero

添加方法仍然不会改变从父浮点类继承的方法,显然会返回一个浮点数。

所以我的问题是:有没有一种巧妙的方法让子类中的所有继承方法返回子类中的结果,而不需要重写所有方法?我想像装饰器@myfloat被自动应用于所有(适用的)继承方法,将其结果从类型float转换为类型myfloat

python python-3.x class inheritance
1个回答
1
投票

这是一种装饰器的方法,它可以减少每个需要进行类型转换的方法的单行数。它甚至包含了@Graipher的self.__class__提示,这使得装饰工作没有变化,以防你有一天重命名myfloat

def cast_return(func):
    """ Decorator that casts the return value of a special __method__
        back to the original type of 'self'. """
    def wrapped(self, *args, **kwargs):
        return self.__class__(func(self, *args, **kwargs))
    return wrapped

class myfloat(float):
    def __truediv__(self, b):
        if b == 0:
            return 'inf'
        else:
            return myfloat(self.__float__() / b)

    __mul__ = cast_return(float.__mul__)
    __add__ = cast_return(float.__add__)
    # repeat for all the needed operations

然后你得到......

In [1]: (myfloat(3.3) +  4) / 0
Out[1]: 'inf'

人们甚至可以更进一步,列出这些函数,将它们全部集中在一个循环中,但我不认为它们是那么多。

但:

如果另一个类型处理操作,它仍然无法工作,如下所示:

In [1]:(4 + myfloat(3.3)) / 0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-45-6537eb18ab79> in <module>()
     16     __add__ = cast_return(float.__add__)
     17 
---> 18 (4 + myfloat(3.3)) / 0

ZeroDivisionError: float division by zero

我真的不知道是否有办法解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.