python 中 __truediv__ 的运算符重载

operator overloading for __truediv__ in python

我正在尝试重载 python 中的除法运算符。

class Fraction:
    def __init__(self,top,bottom):
        def gcd(m, n):
            while m % n != 0:
                old_m = m
                old_n = n
                m = old_n
                n = old_m % old_n
            return n
        common = gcd(top,bottom)
        self.num = top/common
        self.den = bottom/common
    def __str__ (self):
        return str(self.num) + "/" + str(self.den)
    def get_num(self):
        return self.num
    def get_den(self):
        return self.den
    def __add__(self, other_fraction):
        new_num = self.num * other_fraction.den + self.den * other_fraction.num
        new_den = self.den * other_fraction.den
        return Fraction(new_num, new_den)
    def __sub__(self, other_fraction):
        new_num = self.num * other_fraction.den - self.den * other_fraction.num
        new_den = self.den * other_fraction.den
        return Fraction(new_num, new_den)
    def __mul__ (self, other_fraction):
        new_num = self.num * other_fraction.num
        new_den = self.den * other_fraction.den
        return Fraction(new_num, new_den)
    def __truediv__(self, other_fraction):
        new_num = self.num * other_fraction.den
        new_den = self.den * other_fraction.num
        return Fraction(new_num, new_den)

    def __eq__(self, other):
        first_num = self.num * other.den    
        second_num = other.num * self.den
        return first_num == second_num
    
a = Fraction(10,20)
b = Fraction(30,20)
print a
print "numerator is",a.get_num()
print "denominator is",a.get_den()
print "equality is",(a==b)
print "sum is",(a+b)
print "difference is",(a-b)
print "product is",(a*b)
print "division is",(a/b)

但我在 __truediv__ 处收到错误消息:

TypeError: unsupported operand type(s) for /: 'instance' and 'instance'

代码有什么问题?

object.__truediv__() 特殊方法 / 运算符一起使用,然后仅当您将 Python 编译器切换为使用真正的除法:

from __future__ import division

如果您没有使用该导入,/ 运算符会调用 object.__div__() special method(如果存在)。

另一方面,// 运算符调用您未实现的 object.__floordiv__() special method

来自docs:

object.__div__(self, other) 
object.__truediv__(self, other)

The division operator (/) is implemented by these methods. The __truediv__() method is used when __future__.division is in effect, otherwise __div__() is used. If only one of these two methods is defined, the object will not support division in the alternate context; TypeError will be raised instead.

here

A future statement is a directive to the compiler that a particular [python program] should be compiled using syntax or semantics that will be available in a ... future release of Python. The future statement is intended to ease migration to future versions of Python that introduce incompatible changes to the language. It allows use of the new features before the release in which the feature becomes standard.

future_statement: from __future__ import feature

The features recognized by Python 2.x are unicode_literals, print_function, absolute_import, division, generators, nested_scopes and with_statement

现在,一些测试:

~$ python2.7
Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 3/2
1
>>> exit()

~$ python3.2
Python 3.2.3 (v3.2.3:3d0686d90f55, Apr 10 2012, 11:25:50) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 3/2
1.5

所以,你看,/ 运算符的效果在 python 3.x 中发生了变化。您也可以在下面的示例中看到这一点:

class Dog(object):
    def __div__(self, other):
        print("__div__ called")
    def __truediv__(self, other):
        print("__truediv__ called")


Dog() / Dog()

--output:--
~/python_programs$ python2.7 myprog.py 
__div__ called

~/python_programs$ python3.4 myprog.py
__truediv__ called

因为 __truediv__ 不被 python 2.x 中的 / 运算符调用,覆盖 python [=54= 中的 __truediv__ ] 无效。

PEP 238 - PEP 238 -- Changing the Division Operator

We propose the following transitional measures:

    - Classic division will remain the default in the Python 2.x
      series; true division will be standard in Python 3.0.

    - The // operator will be available to request floor[, i.e. integer,] 
      division unambiguously.

    - The future division statement, spelled "from __future__ import
      division", will change the / operator to mean true division
      throughout the [program]

现在,看看这里发生了什么:

from __future__ import division

class Dog(object):
    def __div__(self, other):
        print("__div__ called")
    def __truediv__(self, other):
        print("__truediv__ called")


Dog() / Dog()

--output:--
~/python_programs$ python2.7 myprog.py 
__truediv__ called

~/python_programs$ python3.4 myprog.py
__truediv__ called

现在,您在 python 2.x 中获得 python3.x 运算符的 / 效果。因此,现在您可以覆盖 __truediv__ 以使 / 运算符执行您想要的操作。

注意,如果你想在python3.x中进行整数除法,即3/2 => 1,那么你必须使用//运算符,它由[=实现28=]。同样,如果你在 python 2.x 中执行 from __future__ import division,那么要得到整数除法,你必须使用 // 运算符;如果你想覆盖 class 中的 // 运算符,你需要实现 __floordiv__.