Python 为什么在只有小于等于运算符重载的情况下,大于运算符和不等于运算符仍然有效
我目前正在研究Python是如何实现其运算符重载的。到目前为止,我发现它比C++更吸引人,尤其是在操作符如<代码> */Cu>(或类似的算术运算符)中,它必须处理一个可以从右到左(2×x)和左到右(x* 2)的操作。 我有以下课程作为测试:Python 为什么在只有小于等于运算符重载的情况下,大于运算符和不等于运算符仍然有效,python,operator-overloading,Python,Operator Overloading,我目前正在研究Python是如何实现其运算符重载的。到目前为止,我发现它比C++更吸引人,尤其是在操作符如 */Cu>(或类似的算术运算符)中,它必须处理一个可以从右到左(2×x)和左到右(x* 2)的操作。 我有以下课程作为测试: from math import sqrt class Vector3: def __init__(self, x,y,z): self.x = x self.y = y self.z = z de
from math import sqrt
class Vector3:
def __init__(self, x,y,z):
self.x = x
self.y = y
self.z = z
def __repr__(self):
return 'Vector3(x=%d, y=%d, z=%d)' % (self.x, self.y, self.z)
def __str__(self):
return '[x: %d, y: %d, z: %d]' % (self.x, self.y, self.z)
def length(self):
return sqrt(self.x**2 + self.y**2 + self.z**2)
def __add__(self, vector):
return Vector3(self.x + vector.x, self.y + vector.y, self.z + vector.z)
def __sub__(self, vector):
return Vector3(self.x - vector.x, self.y - vector.y, self.z - vector.z)
def __mul__(self, scalar):
return Vector3(self.x * scalar, self.y * scalar, self.z * scalar)
__rmul__ = __mul__ # Right multiplication equals left multiplication (if this defers, __rmul__ has to be overwritten and defined manually)
def __eq__(self, vector):
return (self.x == vector.x and self.y == vector.y and self.z == vector.z)
def __lt__(self, vector):
return self.length() < vector.length()
@staticmethod
def compareAndPrint(vector1, vector2):
if vector1 == vector2: return 'v1 == v2 since len(v1) = %f == %f = len(v2)' % (vector1.length(), vector2.length())
elif vector1 < vector2: return 'v1 < v2 since len(v1) = %f < %f = len(v2)' % (vector1.length(), vector2.length())
elif vector1 > vector2: return 'v1 > v2 since len(v1) = %f > %f = len(v2)' % (vector1.length(), vector2.length())
v1 = Vector3(1,2,3)
v2 = Vector3(0,-1,1)
v3 = v1 + v2
v4 = v3 - v1
v5 = v1 * 2
v6 = 2 * v1
print(v1)
print(v2)
print(v3)
print(v4)
print(v5)
print(v6)
print(Vector3.compareAndPrint(v1,v2))
print(Vector3.compareAndPrint(v2,v1))
print(Vector3.compareAndPrint(v1,v1))
Python是自动处理的还是我做了一些我没有注意到的事情来实现这一点?我唯一想到的是Python采用了
的倒数是Python中的大多数二进制运算符都可以由任意一个操作数重载。左操作数有一种定义方法,如用于加法的\uuuu add\uuuu
,右操作数有一种定义方法,如\uuuu radd\uu
。我记得唯一一个只能由一个操作数重载的操作数是
中的,它必须由右侧定义
为了便于比较,\uu gt\uuuuuuuuu
和\uuuuuuuuuuuuu
方法与\uuuuuuuuuuuu
方法不同。这意味着当你做left\u thing>right\u thing
和left\u thing
不知道该做什么时,Python会尝试right\u thing
。因为您已经实现了\uuult\uuuuu
,所以这是可行的
请注意,Python不会尝试任何涉及\uuuu le\uuuuuu
、\uu ge\uuuuu
或\uuuu eq\uuuuu
的操作,如果\uu gt\uuuuu
失败。Python中的大多数二进制运算符都可以由任一操作数重载。左操作数有一种定义方法,如用于加法的\uuuu add\uuuu
,右操作数有一种定义方法,如\uuuu radd\uu
。我记得唯一一个只能由一个操作数重载的操作数是
中的,它必须由右侧定义
为了便于比较,\uu gt\uuuuuuuuu
和\uuuuuuuuuuuuu
方法与\uuuuuuuuuuuu
方法不同。这意味着当你做left\u thing>right\u thing
和left\u thing
不知道该做什么时,Python会尝试right\u thing
。因为您已经实现了\uuult\uuuuu
,所以这是可行的
请注意,Python不会尝试任何涉及\uuuu le\uuuuuu
、\uu ge\uuuuu
或\uuuu eq\uuuuu
的操作,如果\uu gt\uuuuuu
失败。这是许多人似乎不理解的Python数据模型的一部分。要在文档中追溯这一点,我们需要从二进制算术运算开始(\uuuuu mul\uuuu
,\uuuu add\uuuu
等)
我们注意到有一个和一个方法。差异在以下文档中描述:
调用这些方法是为了用反射(交换)的操作数实现二进制算术运算(+、-、*、/、%、divmod()、pow()、**、&、^、|)仅当左操作数不支持相应的运算且操作数类型不同时,才会调用这些函数。
现在,当我们查看以下文档时:
这些方法没有交换的参数版本(当左参数不支持该操作而右参数支持该操作时使用);相反,和是彼此的反映
因此,在您的例子中发生的情况是,由于\uugt\uugt
没有被重载,python实际上交换了参数的顺序并调用\ugt\uugt
。相当整洁
FWIW,如果您想要构造一个可以与该类的其他实例一起排序的类,那么decorator非常有用。您只需提供\uu lt\uuuuuuuuuu
和\uuuuueq\uuuuuuu
,其余部分由装饰程序提供。这是一些python数据模型,许多人似乎不理解。要在文档中追溯这一点,我们需要从二进制算术运算开始(\uuuuu mul\uuuu
,\uuuu add\uuuu
等)
我们注意到有一个和一个方法。差异在以下文档中描述:
调用这些方法是为了用反射(交换)的操作数实现二进制算术运算(+、-、*、/、%、divmod()、pow()、**、&、^、|)仅当左操作数不支持相应的运算且操作数类型不同时,才会调用这些函数。
现在,当我们查看以下文档时:
这些方法没有交换的参数版本(当左参数不支持该操作而右参数支持该操作时使用);相反,和是彼此的反映
因此,在您的例子中发生的情况是,由于\uugt\uugt
没有被重载,python实际上交换了参数的顺序并调用\ugt\uugt
。相当整洁
FWIW,如果您想要构造一个可以与该类的其他实例一起排序的类,那么decorator非常有用。你只需提供\ult\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。请看文章的结尾,特别是比较(v1,v2)和(v2,v1)。或者你是说别的什么?不,我的意思是在\uult\uuuuu
和\uuuuuuu eq\uuuuu
中放一些,看看它们什么时候被调用,有什么参数。啊,谢谢你的建议+1为什么不加入一些print
s以查看调用哪些方法以及何时调用?我有打印。请看文章的结尾,特别是比较(v1,v2)和(v2,v1)。或者你是说别的什么?不,我的意思是把一些放在和里面
[x: 1, y: 2, z: 3]
[x: 0, y: -1, z: 1]
[x: 1, y: 1, z: 4]
[x: 0, y: -1, z: 1]
[x: 2, y: 4, z: 6]
[x: 2, y: 4, z: 6]
v1 > v2 since len(v1) = 3.741657 > 1.414214 = len(v2)
v1 < v2 since len(v1) = 1.414214 < 3.741657 = len(v2)
v1 == v2 since len(v1) = 3.741657 == 3.741657 = len(v2)