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.pyclass 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.pyclass 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实例的情况下,我们就可以编写 这样的代码。这项扩展是本步骤的目标。

我们的最终目标是让Variable实例“看起来”像ndarray实例。这样一来,我们就可以像编写NumPy代码一样使用DeZero。对熟悉NumPy的人来说,这将大大降低学习DeZero的成本。
下面扩展Variable,以支持运算符+和*。在此之前,我们需要实现一个执行乘法运算的函数(加法运算已在步骤11实现)。首先实现执行乘法运算的类Mul(Mul是Multiply的缩写)。