19.3_len函数和print函数

19.3 len函数和print函数

为了能使用Python的len函数,下面我们来扩展Variable类。len函数是计算对象数量的函数,是Python的内置函数。下面是它的使用示例。

>>> x = [1, 2, 3, 4]  
>>> len(x)  
4  
>>> x = np.array([1, 2, 3, 4])  
>>> len(x)  
4  
>>> x = np.array([[1, 2, 3], [4, 5, 6]])  
>>> len(x)  
2

如上面的代码所示,对列表等应用len函数后,len函数会返回其中的元

素的数量。对ndarray实例应用len,函数会返回第1个维度的元素数量。下面修改代码,使len函数也可以应用在Variable上。

steps/step19.py
class Variable: deflen_self): return len(self.data)

只要像上面那样实现特殊方法__len__,就能对Variable实例应用len函数了。这样一来,我们可以写出如下所示的代码。

$\mathbf{x} =$  Variable(np.array([[1,2,3],[4,5,6]])) print(len(x))

运行结果

2

在Python中,像__init__和__len__这种具有特殊意义的方法,一般会在名称前后各加两条下划线。

最后添加一个能够轻松查看Variable内容的功能,具体来说就是使用print函数将Variable中的数据打印出来。先看看如何使用这个功能。

$\begin{array}{rl} & {\mathrm{x} = \mathrm{Variable}(\mathrm{np.array}([1,2,3]))}\\ & {\mathrm{print}(\mathrm{x})}\\ & {\mathrm{x} = \mathrm{Variable}(\mathrm{None})}\\ & {\mathrm{print}(\mathrm{x})}\\ & {\mathrm{x} = \mathrm{Variable}(\mathrm{np.array}([[1,2,3],[4,5,6]]))}\\ & {\mathrm{print}(\mathrm{x})} \end{array}$

运行结果

variable([123])   
variable(None)   
variable([[123] [456]])

如果像上面那样将Variable实例传给print函数,要让该函数打印出其中ndarray实例的内容。输出要被字符串variable(...)括起来,以此告诉用户这是一个Variable实例。print函数还支持数据为None的情况和分多行输出的情况。如果分多行输出,可以在第2行后用空格调整字符的起始位置,以改善外观。为了满足以上几点要求,我们按如下方式实现Variable的__repr__方法。

steps/step19.py
class Variable: def __repr__(self): if self.data is None: return 'variable(None)'  $p =$  str(self.data).replace('\\n','\n'  $^+$  '  $\text{串}$  \*9) return 'variable('  $^+$  p  $^+$  ')

我们可以通过重写__repr__方法来自定义print函数输出的字符串。返回值是想要输出的字符串。上面的代码通过str(self.data)将ndarray实例转换为字符串。在幕后,ndarray实例的__str__函数被调用,数值转换为字符串。之后,转换后的字符串会被字符串variable围起来。另外,如果字符串中有换行符(\n),函数会在换行符后插入9个空格。这样一来,在分多行输出的情况下,数字的起始位置就会对齐。

这样就完成了让Variable类成为“透明箱子”的一部分工作。下一个步骤我们将开展后续的工作。

步骤20

运算符重载(1)

在上一个步骤,我们创建了让Variable成为“透明箱子”的机制。不过,这项工作还没有完成,我们还要让Variable支持 ++* 等运算符。这项工作完成后,在a和b是Variable实例的情况下,我们就可以编写 y=aby = a * b 这样的代码。这项扩展是本步骤的目标。

我们的最终目标是让Variable实例“看起来”像ndarray实例。这样一来,我们就可以像编写NumPy代码一样使用DeZero。对熟悉NumPy的人来说,这将大大降低学习DeZero的成本。

下面扩展Variable,以支持运算符+和*。在此之前,我们需要实现一个执行乘法运算的函数(加法运算已在步骤11实现)。首先实现执行乘法运算的类Mul(Mul是Multiply的缩写)。