-
Notifications
You must be signed in to change notification settings - Fork 0
FAQs for Lab 1
这个问题一般情况下是由 pyzmq 版本过高引起的。如果您的 Python 版本为 3.9.x 及以下,应该可以使用将 pyzmq 降级到 19.0.2 的方式解决问题;如果降级之后还不能成功,可以尝试将 Pillow 降级到 8.2.0;如果您的 Python 版本为 3.10.x 及以上,在降级 pyzmq 时应该会报两百多行的错误然后失败。这是因为 pyzmq 19.0.2 存在对 Windows 平台的适配问题。参考 pyzmq 官网上对 version 21.0 更新的说明:
Missing MSVCP140.dll in Python 3.9 wheels on Windows, causing vcruntime-redist package to be required to use the Python 3.9 wheels for pyzmq 20.0
但是,21.0 也是不行的,因为它需要 Microsoft Visual C++ 14.0 以上版本的编译器……
所以这种情况下,建议的方式是使用 anaconda 或 miniconda,直接使用我们给出的 Windows-Env.yml 进行安装,命令为:
conda env create --file 到……的路径\Windows-Env.yml --name 环境名称
然后直接使用此虚拟环境中 Python 3.7.2 的内核进行实验。此虚拟环境中同时配置了以后的实验所需的包,应可用于以后所有实验。
在 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 。
运算符重载就是指,当我对一个类进行加减乘除等操作时,我要进行一些特殊处理。在 Python 的内置类型中可以看到这样的例子,整数加法返回整数,字符串加法返回连接后的字符串,显然,这个 +
符号带有一词多义的特性。当我们使用 a + b
时,事实上它调用了一个方法 __add__
,请看以下代码:
i = 3
i = i.__add__(4)
print(i)
这里的输出结果是 7,正是 3 + 4 运算的结果。这意味着,当我执行 i + 4
的求值时,其求值过程就是 i.__add__(4)
,这是运算符重载的基本原理。
重载(override)是指,当一个新的类继承自原先的类时,我们使用同名函数代替原先类中的同名函数。这样,在新的类调用这个函数时,它就不会调用其父类的同名函数。因此,只需要重载 __add__
函数,即可实现自定义类的加法。关于各个运算符对应的方法,可以参考 Operators 。
在后面的要求中,我们要求实现判断语句。在实现 ==
的过程中,可能会发现,调用 ==
并不会报 NotImplementedError
。原因是任何一个类都继承了一个叫做 type
的基类,其中自带有 __eq__
方法,这个方法对于任何两个不同的实例都会返回 False
。而在原始版本的 Number
类中事实上已经重载了 __eq__
,为了降低难度删去但未删去相关的要求,于是造成了一些混乱。解决的方法就是,在 Rational
类中自己定义 __eq__
方法,也可以选择在 Number
类中加上对应的 NotImplementedError
。
当调用 print
函数时,会调用 __str__
方法,并输出返回值字符串。这是对 __str__
方法的最简单理解。因此,如果对于分母为 1 直接以整数方式输出分子,可以修改原有的 __repr__
和 __str__
方法。
这部分确实超出了我们所提供的内容的范畴。有兴趣的同学可以参考 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
...
这样,当 p
和 q
都为 0 时,构造 Rational(0, 0)
将返回一个 NaN
类的实例。
Embedded Artificial Intelligence @ ZJU