假设我要创建自己的现有类版本。让我们选择内置的float类。在此示例中,我将创建一个类似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类,当我进行任何其他操作(即方法)时,结果将是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


从父float类继承的加法仍然没有改变,显然返回了float。

所以我的问题是:是否有一种巧妙的方法可以使子类中的所有继承方法返回子类中的结果,而无需重写所有方法?我在想像装饰器@myfloat这样的东西会自动应用于所有(适用)继承的方法,以将其结果从类型float转换为类型myfloat

最佳答案

这是一种带有装饰器的方法,它可以将需要类型转换的方法的工作量减少到一行。它甚至还包含@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


我真的不知道有没有解决办法。

10-04 14:42
查看更多