3. 增强赋值算术运算符重载
增强赋值算术运算符重载的方法
方法名和参数
运算符和表达式
说明
__iadd__(self, other)
self += other
加法
__isub__(self, other)
self -= other
减法
__imul__(self, other)
self *= other
乘法
__itruediv__(self, other)
self /= other
除法
__ifloordiv__(self, other)
self //= other
整数(地板除)
__imod__(self, other)
self %= other
求余(取模)
__ipow__(self, other)
self **= other
幂
__imatmul__(self, other)
self @= other
矩阵乘法
示例
# 增强赋值算术运算符重载 示例
# http://weimingze.com
class Vector3D:
'''用于描述三维向量的类!,x,y,z分别是向量的坐标位置!'''
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def __repr__(self):
return f'Vector3D({self.x},{self.y},{self.z})'
def __mul__(self, other):
return Vector3D(
self.x * other, self.y * other,
self.z * other)
def __imul__(self, other):
self.x *= other
self.y *= other
self.z *= other
return self
v1 = Vector3D(1, 2, 3)
print("v1:", v1)
print(id(v1))
v1 *= 3 # v1.__imul__(3) # v1 = v1.__mul__(3)
print('v1:', v1)
print(id(v1))
运行结果
v1: Vector3D(1,2,3)
4358500240
v1: Vector3D(3,6,9)
4358500240
去掉 __imul__
方法,程序运行结果相同,只是ID会有变化。此时 v1 *= 3 后 v1绑定的不是原对象。
示例
# 增强赋值算术运算符重载 示例
# http://weimingze.com
class Vector3D:
'''用于描述三维向量的类!,x,y,z分别是向量的坐标位置!'''
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def __repr__(self):
return f'Vector3D({self.x},{self.y},{self.z})'
def __mul__(self, other):
return Vector3D(
self.x * other, self.y * other,
self.z * other)
v1 = Vector3D(1, 2, 3)
print("v1:", v1)
print(id(v1))
v1 *= 3 # v1.__imul__(3) # v1 = v1.__mul__(3)
print('v1:', v1)
print(id(v1))
运行结果
v1: Vector3D(1,2,3)
4404751936
v1: Vector3D(3,6,9)
4406038032
增强赋值算术运算符的运算规则说明
以增强赋值算术运算符 x += y
为例,此运算符会优先调用 x.__iadd__(y)
方法,如果没有__iadd__()
方法时会将增强赋值运算拆解为 x = x + y
,然后调用 x = x.__add__(y)
方法;如果再不存在 __add__()
方法则会触发 TypeError 异常。
其它增强赋值算术运算符也具有相同的规则。
问题
以下两个程序打印结果是什么?为什么不一样?
f1 函数传入列表的程序运行:
# --- 以下用列表 ---
L = [1, 2, 3]
def f1(lst):
lst += [4, 5, 6]
f1(L)
print(L) # [1, 2, 3, 4, 5, 6]
f1 函数传入元组的程序运行:
# --- 以下用元组 ---
L = (1, 2, 3)
def f1(lst):
lst += (4, 5, 6)
f1(L)
print(L) # (1, 2, 3)