例: Fraction

重写 __init__ 方法

要创建一个 Fraction 对象,需要提供分子和分母两部分数据。在 Python 中,构造方法总是命名为 __init__ (即在 init 的前后分别有两个下划线)

Fraction 类及其构造方法:

class Fraction:

    def __init__(self, top, bottom):

        self.num = top
        self.den = bottom

注意:形式参数列表包含 3 项。 self 是一个总是指向对象本身的特殊参数,它必须是第一个形式参数。

构造方法中的 self.num 定义了 Fraction 对象有一个叫作 num内部数据对象作为其状态的一部分。同理, self.den 定义了分母。这两个实际参数的值在初始时赋给了状态,使得新创建的 Fraction 对象能够知道其初始值。

要创建 Fraction 类的实例,必须调用构造方法。使用类名并且传入状态的实际值就能完成调用(注意,不要直接调用 __init__)。

myfraction = Fraction(3,5)

以上代码创建了一个对象,名为 myfraction,值为 3/5。

打印 Fraction 对象:

>>> myf = Fraction(3,5)
>>> print(myf)
<__main__.Fraction instance at 0x409b1acc>

Fraction 对象 myf 并不知道如何响应打印请求。 print 函数要求对象将自己转换成一个可以被写到输出端的字符串。 myf 唯一能做的就是显示存储在变量中的实际引用(地址本身)。这不是我们想要的结果。

重写 __str__ 方法

解决方法一:show 方法

def show(self):
    print(self.num, "/", self.den)

解决方法二:将对象转换成字符串(__str__ 方法)

def __str__(self):
    return str(self.num) + "/" + str(self.den)

定义一个名为 __str__ 的方法,重写默认实现,或者说重新定义该方法的行为。

一旦要求 Fraction 对象转换成字符串,就会返回结果。

>>> myf = Fraction(3,5)
>>> print(myf)
3/5
>>> print("I ate", myf, "of the pizza")
I ate 3/5 of the pizza
>>> myf.__str__()
'3/5'
>>> str(myf)
'3/5'
>>>

重写 __add__ 方法

__add__ 方法需要两个参数。第一个仍然是 self,第二个代表了表达式中的另一个操作数。

f1.__add__(f2)

以上代码会要求 Fraction 对象 f1Fraction 对象 f2 加到自己的值上。可以将其写成标准表达式: f1 + f2

def __add__(self, otherfraction):

    newnum = self.num * otherfraction.den + \
        self.den * otherfraction.num
    newden = self.den * otherfraction.den

    return Fraction(newnum, newden)

两个分数需要有相同的分母才能相加,确保分母相同最简单的方法是使用两个分母的乘积作为分母。

>>> f1 = Fraction(1, 4)
>>> f2 = Fraction(1, 2)
>>> f3 = f1 + f2
>>> print(f3)
6/8
>>>

gcd 函数

虽然这一方法能够与我们预想的一样执行加法运算,但它并不是最简分数。为了保证结果总是最简分数,需要化简分数。我们需要寻找分子和分母的最大公因数(greatest commondivisor, GCD),然后将分子和分母分别除以最大公因数,最后的结果就是最简分数。

欧几里得算法:对于整数 m 和 n,如果 m 能被 n 整除,那么它们的最大公因数就是 n。然而,如果 m 不能被n 整除,那么结果是 n 与 m 除以 n 的余数的最大公因数。

def gcd(m,n):
    while m%n != 0:
        oldm = m
        oldn = n

        m = oldn
        n = oldm%oldn
    return n

注意:这种实现只有在分母为正的时候才有效。

改良版add方法:

def __add__(self, otherfraction):
    newnum = self.num * otherfraction.den + \
        self.den * otherfraction.num
    newden = self.den * otherfraction.den
    common = gcd(newnum, newden)
    return Fraction(newnum//common, newden//common)

重写 __eq__ 方法

假设有两个 Fraction 对象, f1f2。只有在它们是同一个对象的引用时, f1 == f2 才为 True,这被称为浅相等

Fraction 类中,可以通过统一两个分数的分母并比较分子来实现 __eq__ 方法。

def __eq__(self, other):
    firstnum = self.num * other.den
    secondnum = other.num * self.den

    return firstnum == secondnum

注意:其他的关系运算符也可以被重写。例如, __le__ 方法提供判断小于等于的功能。

Fraction 类的完整实现:

class Fraction:

    def __init__(self, top, bottom):

        self.num = top
        self.den = bottom

    def __str__(self):
        return str(self.num) + "/" + str(self.den)

    def show(self):
        print(self.num, "/", self.den)

    def __add__(self, otherfraction):
        newnum = self.num * otherfraction.den + \
            self.den * otherfraction.num
        newden = self.den * otherfraction.den
        common = gcd(newnum, newden)
        return Fraction(newnum//common, newden//common)

    def __eq__(self, other):
        firstnum = self.num * other.den
        secondnum = other.num * self.den

        return firstnum == secondnum
文章目录