深刻了解 python 虚拟机:魔术办法之数学计算

在本篇文章当中次要给大家介绍在 python 当中一些常见的魔术办法,本篇文章次要是对于与数学计算相干的一些魔术办法,在很多科学计算的包当中都应用到了这些魔术办法。

大小比拟

当咱们在Python中定义本人的类时,能够通过重写一些非凡办法来扭转对象的比拟行为。这些非凡办法包含__lt____le____eq____ne____gt____ge__,它们别离对应于小于、小于等于、等于、不等于、大于和大于等于的比拟运算符。这些办法容许咱们自定义对象之间的比拟规定。

上面是对每个办法的具体介绍:

  • object.__lt__(self, other) 这个办法用于定义小于(<)运算符的行为。当咱们应用小于运算符比拟两个对象时,会调用该办法。如果self对象小于other对象,则返回True,否则返回False
  • object.__le__(self, other) 这个办法用于定义小于等于(<=)运算符的行为。当咱们应用小于等于运算符比拟两个对象时,会调用该办法。如果self对象小于等于other对象,则返回True,否则返回False
  • object.__eq__(self, other) 这个办法用于定义等于(==)运算符的行为。当咱们应用等于运算符比拟两个对象时,会调用该办法。如果self对象等于other对象,则返回True,否则返回False
  • object.__ne__(self, other) 这个办法用于定义不等于(!=)运算符的行为。当咱们应用不等于运算符比拟两个对象时,会调用该办法。如果self对象不等于other对象,则返回True,否则返回False
  • object.__gt__(self, other) 这个办法用于定义大于(>)运算符的行为。当咱们应用大于运算符比拟两个对象时,会调用该办法。如果self对象大于other对象,则返回True,否则返回False
  • object.__ge__(self, other) 这个办法用于定义大于等于(>=)运算符的行为。当咱们应用大于等于运算符比拟两个对象时,会调用该办法。如果self对象大于等于other对象,则返回True,否则返回False

这些比拟办法容许咱们依据本人的需要自定义对象的比拟规定。当咱们应用比拟运算符对对象进行比拟时,Python会主动调用这些办法,并返回相应的后果。

上面是一个简略的示例,展现如何在自定义类中应用这些比拟办法:

class Point:    def __init__(self, x, y):        self.x = x        self.y = y        def __lt__(self, other):        return self.x < other.x and self.y        return self.y < other.y        def __le__(self, other):        return self.x <= other.x and self.y <= other.y        def __eq__(self, other):        return self.x == other.x and self.y == other.y        def __ne__(self, other):        return not self.__eq__(other)        def __gt__(self, other):        return self.x > other.x and self.y > other.y        def __ge__(self, other):        return self.x >= other.x and self.y >= other.yp1 = Point(1, 2)p2 = Point(3, 4)print(p1 < p2)  print(p1 <= p2)print(p1 == p2)print(p1 != p2)print(p1 > p2)print(p1 >= p2)

下面的代码输入后果如下所示:

2TrueFalseTrueFalseFalse

在下面的示例中,咱们定义了一个名为Point的类,它示意一个二维立体上的点。咱们重写了__lt____le____eq____ne____gt____ge__办法来定义点之间的比拟规定。依据咱们的定义,如果一个点的x坐标和y坐标都小于另一个点的相应坐标,则咱们认为前一个点小于后一个点。

通过创立两个Point对象并应用比拟运算符进行比拟,咱们能够看到依据咱们的定义,比拟运算符返回了预期的后果。

模仿设计一个数学类型

当咱们在Python中定义本人的类时,能够通过重写一些非凡办法来扭转对象的算术运算行为。这些非凡办法包含__add____sub____mul____matmul____truediv____floordiv____mod____divmod____pow____lshift____rshift____and____xor____or__,它们别离对应于加法、减法、乘法、矩阵乘法、真除法、整除法、取模运算、divmod函数、幂运算、左移位、右移位、按位与、按位异或和按位或的运算符。这些办法容许咱们自定义对象之间的算术运算规定。

  • object.__add__(self, other) 这个办法用于定义加法(+)运算符的行为。当咱们应用加法运算符对两个对象进行相加时,会调用该办法。它返回两个对象相加的后果。
  • object.__sub__(self, other) 这个办法用于定义减法(-)运算符的行为。当咱们应用减法运算符对两个对象进行相减时,会调用该办法。它返回两个对象相减的后果。
  • object.__mul__(self, other) 这个办法用于定义乘法(*)运算符的行为。当咱们应用乘法运算符对两个对象进行相乘时,会调用该办法。它返回两个对象相乘的后果。
  • object.__matmul__(self, other) 这个办法用于定义矩阵乘法(@)运算符的行为。当咱们应用矩阵乘法运算符对两个对象进行矩阵乘法时,会调用该办法。它返回两个对象的矩阵乘法后果。
  • object.__truediv__(self, other) 这个办法用于定义真除法(/)运算符的行为。当咱们应用真除法运算符对两个对象进行相除时,会调用该办法。它返回两个对象相除的后果。
  • object.__floordiv__(self, other) 这个办法用于定义整除法(//)运算符的行为。当咱们应用整除法运算符对两个对象进行相除并取整时,会调用该办法。它返回两个对象相除取整的后果。
  • object.__mod__(self, other) 这个办法用于定义取模(%)运算符的行为。当咱们应用取模运算符对两个对象进行取模运算时,会调用该办法。它返回两个对象取模运算的后果。
  • object.__divmod__(self, other)这个办法用于定义divmod函数的行为。divmod函数承受两个参数,并返回一个蕴含商和余数的元组。当咱们对两个对象应用divmod函数时,会调用该办法。它返回一个蕴含两个对象的商和余数的元组。
  • object.__pow__(self, other[, modulo]) 这个办法用于定义幂运算(**)运算符的行为。当咱们应用幂运算符对两个对象进行幂运算时,会调用该办法。它返回两个对象的幂运算后果。可选的modulo参数用于指定取模运算的模数。
  • object.__lshift__(self, other) 这个办法用于定义左移位(<<)运算符的行为。当咱们对一个对象应用左移位运算符时,会调用该办法。它返回对象左移指定位数后的后果。
  • object.__rshift__(self, other) 这个办法用于定义右移位(>>)运算符的行为。当咱们对一个对象应用右移位运算符时,会调用该办法。它返回对象右移指定位数后的后果。
  • object.__and__(self, other) 这个办法用于定义按位与(&)运算符的行为。当咱们对两个对象应用按位与运算符时,会调用该办法。它返回两个对象按位与的后果。
  • object.__xor__(self, other) 这个办法用于定义按位异或(^)运算符的行为。当咱们对两个对象应用按位异或运算符时,会调用该办法。它返回两个对象按位异或的后果。
  • object.__or__(self, other) 这个办法用于定义按位或(|)运算符的行为。当咱们对两个对象应用按位或运算符时,会调用该办法。它返回两个对象按位或的后果。

通过重写这些办法,咱们能够在自定义类中定义对象之间的算术运算规定。当咱们应用相应的算术运算符或函数对对象进行操作时,Python会主动调用这些办法,并返回相应的后果。

上面是一个简略的示例,展现如何在自定义类中应用这些算术办法:

class Vector:    def __init__(self, x, y):        self.x = x        self.y = y    def __add__(self, other):        return Vector(self.x + other.x, self.y + other.y)    def __sub__(self, other):        return Vector(self.x - other.x, self.y - other.y)    def __mul__(self, scalar):        return Vector(self.x * scalar, self.y * scalar)    def __truediv__(self, scalar):        return Vector(self.x / scalar, self.y / scalar)    def __repr__(self):        return f"Vector[{self.x}, {self.y}]"# 创立两个 Vector 对象v1 = Vector(1, 2)v2 = Vector(3, 4)# 应用算术运算符进行操作v3 = v1 + v2v4 = v1 - v2v5 = v1 * 2v6 = v2 / 3print(f"{v1 = }")print(f"{v2 = }")print(f"{v3 = }")print(f"{v4 = }")print(f"{v5 = }")print(f"{v6 = }")

下面的代码输入后果如下所示:

v1 = Vector[1, 2]v2 = Vector[3, 4]v3 = Vector[4, 6]v4 = Vector[-2, -2]v5 = Vector[2, 4]v6 = Vector[1.0, 1.3333333333333333]

在下面的示例中,咱们定义了一个名为Vector的类,它示意二维向量。咱们重写了__add____sub____mul____truediv__办法来定义向量之间的加法、减法、乘法和真除法的规定。依据咱们的定义,向量的加法是将对应的重量相加,向量的减法是将对应的重量相减,向量的乘法是将每个重量与标量相乘,向量的真除法是将每个重量除以标量。通过创立两个Vector对象并应用算术运算符进行操作,咱们能够看到依据咱们的定义,算术运算符返回了预期的后果。

当咱们在Python中定义本人的类时,除了重写一些魔术办法来扭转对象的算术运算行为之外,还能够重写对应的反向魔术办法来解决反向运算。这些反向魔术办法以__r结尾,前面跟着对应的运算符,例如__radd____rsub____rmul__等。它们用于在无奈间接对另一个对象调用相应的魔术办法时,尝试应用以后对象的魔术办法来解决反向运算。次要有上面的办法:

object.__iadd__(self, other)object.__isub__(self, other)object.__imul__(self, other)object.__imatmul__(self, other)object.__itruediv__(self, other)object.__ifloordiv__(self, other)object.__imod__(self, other)object.__ipow__(self, other[, modulo])object.__ilshift__(self, other)object.__irshift__(self, other)object.__iand__(self, other)object.__ixor__(self, other)object.__ior__(self, other)

比方 a + b,当 a 当中没有定义 __add__的时候,就会调用 b 的 __radd__ 。比方上面这个例子:

class A:    def __init__(self, x):        self.x = x        class B:    def __init__(self, x):        self.x = x    def __radd__(self, other):        print("In B __radd__")        return self.x + other.xif __name__ == '__main__':    a = A(1)    b = B(1)    print(a + b)

下面的代码输入后果如下所示:

In B __radd__2

除了下面对于数据的魔术办法之外,还有一些其余的魔术办法,具体如下所示:

object.__neg__(self)object.__pos__(self)object.__abs__(self)object.__invert__(self)object.__complex__(self)object.__int__(self)object.__float__(self)object.__index__(self)object.__round__(self[, ndigits])object.__trunc__(self)object.__floor__(self)object.__ceil__(self)
  • object.__neg__(self) 这个办法用于定义负号(-)运算符的行为。当利用负号运算符到一个对象时,会调用该对象的__neg__办法。它返回一个示意以后对象相反数的新对象。
  • object.__pos__(self) 这个办法用于定义正号(+)运算符的行为。当利用正号运算符到一个对象时,会调用该对象的__pos__办法。它返回以后对象的正本。
  • object.__abs__(self) 这个办法用于定义绝对值(abs())函数的行为。当利用abs()函数到一个对象时,会调用该对象的__abs__办法。它返回以后对象的绝对值。
  • object.__invert__(self) 这个办法用于定义按位取反(~)运算符的行为。当利用按位取反运算符到一个对象时,会调用该对象的__invert__办法。它返回以后对象按位取反后的后果。
  • object.__complex__(self) 这个办法用于定义complex()函数的行为,用于将对象转换为复数模式。当利用complex()函数到一个对象时,会调用该对象的__complex__办法。它返回一个复数对象,示意以后对象。
  • object.__int__(self) 这个办法用于定义int()函数的行为,用于将对象转换为整数模式。当利用int()函数到一个对象时,会调用该对象的__int__办法。它返回一个整数对象,示意以后对象。
  • object.__float__(self) 这个办法用于定义float()函数的行为,用于将对象转换为浮点数模式。当利用float()函数到一个对象时,会调用该对象的__float__办法。它返回一个浮点数对象,示意以后对象。
  • object.__index__(self) 这个办法用于定义operator.index()函数的行为,用于将对象转换为整数索引。当利用operator.index()函数到一个对象时,会调用该对象的__index__办法。它返回一个整数对象,示意以后对象能够用作索引。
  • object.__round__(self[, ndigits]) 这个办法用于定义round()函数的行为,用于对对象进行四舍五入。当利用round()函数到一个对象时,会调用该对象的__round__办法。可选的ndigits参数指定小数位数,默认为None。它返回一个新的对象,示意以后对象四舍五入后的后果。
  • object.__trunc__(self) 这个办法用于定义math.trunc()函数的行为,用于将对象截断为整数。当利用math.trunc()函数到一个对象时,会调用该对象的__trunc__办法。

总结

本篇文章介绍了在Python中应用魔术办法来扭转对象的比拟和算术运算行为。对于比拟运算符,能够通过重写__lt____le____eq____ne____gt____ge__办法来定义自定义对象之间的比拟规定。对于算术运算符,能够通过重写__add____sub____mul____matmul____truediv____floordiv____mod____divmod____pow____lshift____rshift____and____xor____or__办法来定义对象之间的算术运算规定。这些办法容许自定义类的对象具备与内置类型类似的行为。

本篇文章还提到了反向魔术办法,即以__r结尾的办法,用于解决反向运算。例如,__radd____rsub____rmul__等办法能够定义对象在反向运算中的行为。

通过示例代码,文章演示了如何在自定义类中重写这些魔术办法,以实现自定义的比拟和算术运算规定。最初,展现了在自定义类中应用这些办法时失去的预期后果。

总而言之,通过了解和应用这些魔术办法,咱们能够在Python中更好地管制自定义类对象的比拟和算术运算行为,使其更合乎特定需要。


本篇文章是深刻了解 python 虚拟机系列文章之一,文章地址:https://github.com/Chang-LeHung/dive-into-cpython

更多精彩内容合集可拜访我的项目:https://github.com/Chang-LeHung/CSCore

关注公众号:一无是处的钻研僧,理解更多计算机(Java、Python、计算机系统根底、算法与数据结构)常识。