运算符在python中为__truediv__重载

sud*_* ks 6 python overloading operator-keyword python-2.7

我试图在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)
Run Code Online (Sandbox Code Playgroud)

但这__truediv__是错误的

TypeError:/:'instance'和'instance'的不支持的操作数类型

请帮忙解释代码有什么问题?

Mar*_*ers 12

object.__truediv__()特殊方法用于与/运营商,那么只有当你切换的Python编译器使用真司:

from __future__ import division
Run Code Online (Sandbox Code Playgroud)

如果您没有使用该导入,则/运算符会调用object.__div__()特殊方法(如果存在).

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


7st*_*tud 11

来自文档:

object.__div__(self, other) 
object.__truediv__(self, other)
Run Code Online (Sandbox Code Playgroud)

除法运算符(/)由这些方法实现.该 __truediv__()方法__future__.division在有效时使用,否则__div__()使用.如果只定义了这两种方法中的一种,则该对象将不支持备用上下文中的除法; 将引发TypeError.

在这里:

未来的声明是编译器的一个指令,即应该使用将来在Python的未来版本中提供的语法或语义来编译特定的[python程序].未来的声明旨在简化向未来版本的Python的迁移,从而引入对语言的不兼容更改.它允许在发布之前使用新功能,其中功能成为标准.

future_statement: from __future__ import feature
Run Code Online (Sandbox Code Playgroud)

Python 2.x识别的功能是unicode_literals,print_function,absolute_import,division,generators,nested_scopes和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
Run Code Online (Sandbox Code Playgroud)

所以,你看,/运算符的效果在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
Run Code Online (Sandbox Code Playgroud)

因为python 2.x中__truediv__/操作符没有调用,所以在python 2.x中覆盖__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]
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

现在,您将/在python 2.x中获得运算符的python3.x效果.所以,现在你可以覆盖__truediv__以使/操作员做你想做的事.

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