博客 / 詳情

返回

深入理解 python 虛擬機:魔術方法之數學計算

深入理解 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.y


p1 = 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)

上面的代碼輸出結果如下所示:

2
True
False
True
False
False

在上面的示例中,我們定義了一個名為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 + v2
v4 = v1 - v2

v5 = v1 * 2
v6 = v2 / 3

print(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.x


if __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、計算機系統基礎、算法與數據結構)知識。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.