1. 程式人生 > 其它 >Python進階 - 特殊方法的使用

Python進階 - 特殊方法的使用

1.什麼是特殊方法?

特殊方法可以理解為在呼叫內建方法時,程式背後真正被呼叫的方法,通常以雙下劃線開頭和結尾,例如 __len__,有些地方也稱其為"魔術方法"(Magic Method)。
比如,我們比較兩個數的大小時,一般都會使用大於號或小於號進行判斷:

# 命令列呼叫
>>> 1 < 2
True

實際上是在呼叫 __lt__() 方法:

# 命令列呼叫
>>> int.__lt__(1, 2)
True

2.特殊方法有什麼用?

既然程式都已經自動呼叫了,那它有什麼用呢?其實,它更多的用於我們自己編寫的類中。下面我們自行編寫一個向量類:

class Vector:
   def __init__(self, x=0, y=0):
       self.x = x  # x座標
       self.y = y  # y座標

我們在建立好兩個向量例項後,發現單獨顯示的貌似時地址,將兩個向量相加時也直接報錯了,跟我們預想的完全不一樣:

# 命令列呼叫
>>> v1 = Vector(1, 1)
>>> v1
<__main__.Vector object at 0x0000013C5E4CC9D0>
>>> v2 = Vector(2, 3)
>>> v2
<__main__.Vector object at 0x0000013C5E4CC8B0>
>>> v1 + v2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'
>>>

這時候特殊方法就派上用場了。下面通過完善這個向量類,介紹幾款常用的特殊方法。

3.幾款常用的特殊方法

__repr__() 這個方法的主要作用是將一個物件用字串的形式輸出,便於我們進行辨認。
對於我們這個向量類,我們想讓每個向量例項都輸出成“Vector(m, n)”這樣的格式,所以我們就可以使用 __repr__() 方法進行定義:

class Vector:
    def __init__(self, x=0, y=0): 
        self.x = x
        self.y = y
    def __repr__(self):
        # 定義Vector類的物件的字串返回格式
        return 'Vector({}, {})'.format(self.x, self.y)

# 輸出結果
>>> v1 = Vector(1, 1)
>>> v1
Vector(1, 1)

可以看到,輸出的結果符合我們的預期。我們繼續通過幾個特殊方法來完成向量的模、加法以及數乘等操作:

from math import hypot

class Vector:
    def __init__(self, x=0, y=0): 
        self.x = x
        self.y = y
    def __repr__(self):
        # 定義Vector類的物件的字串返回格式
        return 'Vector({}, {})'.format(self.x, self.y)
    def __abs__(self):
        # 通過計算x,y座標的歐幾里得距離,返回向量的模
        return hypot(self.x, self.y)
    def __bool__(self):
        # 判斷向量的模是否為0,從而進行布林運算
        return bool(abs(self))
    def __add__(self, other):
        # 定義兩個向量的加法
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)
    def __mul__(self, scalar):
        # 定義一個數scalar與向量的乘積
        return Vector(self.x * scalar, self.y * scalar)

# 命令列呼叫
>>> v1 = Vector(1, 2)    # 定義向量v1的座標為(1, 2)
>>> v2 = Vector(2, 2)    # 定義向量v2的座標為(2, 2)
>>> v1
Vector(1, 2)
>>> v2
Vector(2, 2)
>>> v1 + v2    # 向量相加
Vector(3, 4)
>>> v1 * 3      # 向量的數乘
Vector(3, 6)
>>> abs(v1 + v2)    # 求 v1 + v2 的模
5.0
>>> bool(v1)    # 對向量v1進行布林運算True
>>> bool(Vector(0, 0))    # 對向量(0, 0)進行布林運算
False

通過對一系列特殊方法進行定義,我們基本上完成了向量的基本操作。這讓我們這個Vector類變得生動起來。

4.特殊方法的意義

通過在自定義的類中重寫一些原生類方法背後的特殊方法,可以使得自定義的類也擁有和原生類相同的訪問、操作方式,讓使用者儘量不會感受到自定義類與原生類的差異,從而保持語言上的一致性。

5.如何查詢特殊方法?

通過Python語言參考手冊的“Data Model”,可以查詢到83個特殊方法的名字,其中47個用於實現算術運算、位運算和比較操作。



注:文章內容出自《流暢的Python》第一章