Skip to content

FAQs for Lab 1

FrightenedFox edited this page Mar 19, 2022 · 3 revisions

Lab 1 常见问题汇总

关于异常处理:如何抛出异常?

在 Python 中,raise 语句专门用于抛出异常(exception)。异常的意思是,程序遇到了设计者不愿意看到的情况,例如在 Rational 类初始化的时候分母为 0,就应该抛出一个 ZeroDevisionError,以提醒调用者这里出现了除零异常。如果要捕获这个异常,可以使用 try except finally 语句,例如:

def raiseError():
    raise NotImplementedError("This function shouldn't be called!")

if __name__ == "__main__":
    try:
        raiseError()
    except NotImplementedError:
        print("An exception flew by!")
    finally:
        print("This will always be printed")

关于异常和异常处理的更多信息,可以参考 Built-in Exceptions

关于运算符重载:__add__ 方法是个啥?

运算符重载就是指,当我对一个类进行加减乘除等操作时,我要进行一些特殊处理。在 Python 的内置类型中可以看到这样的例子,整数加法返回整数,字符串加法返回连接后的字符串,显然,这个 + 符号带有一词多义的特性。当我们使用 a + b 时,事实上它调用了一个方法 __add__,请看以下代码:

i = 3
i = i.__add__(4)
print(i)

这里的输出结果是 7,正是 3 + 4 运算的结果。这意味着,当我执行 i + 4 的求值时,其求值过程就是 i.__add__(4),这是运算符重载的基本原理。

重载(override)是指,当一个新的类继承自原先的类时,我们使用同名函数代替原先类中的同名函数。这样,在新的类调用这个函数时,它就不会调用其父类的同名函数。因此,只需要重载 __add__ 函数,即可实现自定义类的加法。关于各个运算符对应的方法,可以参考 Operators

关于 __eq__ 方法和等于判断

在后面的要求中,我们要求实现判断语句。在实现 == 的过程中,可能会发现,调用 == 并不会报 NotImplementedError 。原因是任何一个类都继承了一个叫做 type 的基类,其中自带有 __eq__ 方法,这个方法对于任何两个不同的实例都会返回 False。而在原始版本的 Number 类中事实上已经重载了 __eq__,为了降低难度删去但未删去相关的要求,于是造成了一些混乱。解决的方法就是,在 Rational 类中自己定义 __eq__ 方法,也可以选择在 Number 类中加上对应的 NotImplementedError

关于 __repr____str__

当调用 print 函数时,会调用 __str__ 方法,并输出返回值字符串。这是对 __str__ 方法的最简单理解。因此,如果对于分母为 1 直接以整数方式输出分子,可以修改原有的 __repr____str__ 方法。

关于 NaN 等类的实现

这部分确实超出了我们所提供的内容的范畴。有兴趣的同学可以参考 Data Model 中对类生成的描述,重载 __new__ 方法来尝试实现。例如,我们以 NaN 为例,在 Rational 类中应该如此定义:

class Rational:
    ...

    def __init__(self, p, q):
        if p == 0:
            self.q = 1
        self._simplify()

    def __new__(cls, p, q):
        obj = object.__new__(cls)
        obj.p = p
        obj.q = q
        if p == 0 and q == 0:
            return NaN()
        return obj

    ...

这样,当 pq 都为 0 时,构造 Rational(0, 0) 将返回一个 NaN 类的实例。

Clone this wiki locally