7.2 算术运算符的特殊方法
一共有13个二进制运算符以及相关的特殊方法。先关注一些常用的算术运算符。如下面表格所示,每个特殊方法名对应一个各自的运算符(函数)。
方法 | 运算符 |
|---|---|
object. add (self, other) | + |
object. sub (self, other) | - |
object. mul (self, other) | |
object. truediv (self, other) | / |
object. floordiv (self, other) | // |
object. mod (self, other) | % |
object. divmod (self, other) | divmod() 函数 |
object. pow (self, other[, modulo]) | pow() 函数和 * |
以上运算符中包含了两个函数。还有很多特殊方法,也对应了一元运算符和函数,如下表所示。
方法 | 运算符 |
|---|---|
object. neg (self) | - |
object. pos (self) | + |
object. abs (self) | abs() 函数 |
object. complex (self) | complex() 函数 |
object. int (self) | int() 函数 |
object. float (self) | float() 函数 |
object. round (self[, n]) | round() 函数 |
object. trunc (self[, n]) | math.trunc() 函数 |
object. ceil (self[, n]) | math.ceil() 函数 |
object. floor (self[, n]) | math.floor() 函数 |
以上列表包含了很多函数。可以使用Python的内部追踪,看看内部的具体细节。以下定义了一个简单的追踪函数,来看一下其中的部分细节。
def trace( frame, event, arg ):
if frame.fcode.coname.startswith(""):
print( frame.f_code.co_name, frame.f_code.co_filename, event )
这个函数会打印出名称以"__"为起始的特殊方法名称,可以使用如下代码把这个追踪函数安装到Python中。
import sys
sys.settrace(trace)
一旦完成安装,系统中任何执行代码都会经过trace()函数。我们会过滤出所有特殊方法名的事件。接下来会定义一个内部类的子类,以探究方法的解析规则。
class noisyfloat( float ):
def add( self, other ):
print( self, "+", other )
return super().add( other )
def radd( self, other ):
print( self, "r+", other )
return super().radd( other )
这个类只重载了运算符中的两个特殊方法。当执行noisyfloat值的加法时,会看到打印出的运算符相关的统计信息。而且,追踪信息会告诉我们发生了什么。如下代码演示了Python为一个给定运算符选择类的过程。
>>> x = noisyfloat(2)
>>> x+3
add <stdin> call
2.0 + 3
5.0
>>> 2+x
radd <stdin> call
2.0 r+ 2
4.0
>>> x+2.3
add <stdin> call
2.0 + 2.3
4.3
>>> 2.3+x
radd <stdin> call
2.0 r+ 2.3
4.3
从x+3开始,可以看到noisyfloat+int是如何将int对象值3提供给add()方法的。这个值传入了基类float中,将3转换为float类型并做加法。而2+x则演示了noisyfloat类的运算符右边的加法函数是如何被调用的。int再次被传入基类中进而被转换为float。对于表达式x+2.3,我们得知noisyfloat+float使用了运算符左边的子类中的加法函数。相应地,对于表达式2.3+x而言,float+noisyfloat则使用了运算符右边的子类中的反向加法函数radd()。
