淺談Python類名稱空間

2020-07-16 10:05:03
前面章節中,已經不只一次提到,所有位於 class 語句中的程式碼,其實都位於特殊的名稱空間中,通常稱之為類名稱空間。Python 中,編寫的整個程式預設處於全域性名稱空間內,而類體則處於類名稱空間內。

Python 允許在全域性範圍內放置可執行程式碼,當 Python 執行該程式時,這些程式碼就會獲得執行的機會。類似地,Python 同樣允許在類範圍內放置可執行程式碼,當 Python 執行該類定義肘,這些程式碼同樣會獲得執行的機會。

例如,如下程式測試了類名稱空間:
class Item:
    # 直接在類空間中放置執行性質程式碼
    print('正在定義Item類')
    for i in range(10):
        if i % 2 == 0 :
            print('偶數:', i)
        else:
            print('奇數:', i)
執行結果為:

正在定義Item類
偶數: 0
奇數: 1
偶數: 2
奇數: 3
偶數: 4
奇數: 5
偶數: 6
奇數: 7
偶數: 8
奇數: 9

正如從上面程式碼所看到的,程式直接在 Item 類體中放置普通的輸出語句、迴圈語句、分支語句,這都是合法的。當程式執行 Item 類時,Item 類名稱空間中的這些程式碼都會被執行。

從執行效果來看,這些可執行程式碼被放在 Python 類名稱空間與全域性空間並沒有太大的區別。確實如此,這是因為程式並沒有定義“成員”(變數或函數),這些程式碼執行之後就完了,不會留下什麼。

但下面程式碼就有區別。下面程式碼示範了在全域性空間和類名稱空間內分別定義 lambda 表示式:
global_fn = lambda p: print('執行lambda表示式,p引數: ', p)
class Category:
    cate_fn = lambda p: print('執行lambda表示式,p引數: ', p)
# 呼叫全域性範圍內的global_fn,為引數p傳入引數值
global_fn('fkit')  # ①
c = Category()
# 呼叫類名稱空間內的cate_fn,Python自動系結第一個引數
c.cate_fn()  # ②
上面程式分別在全域性空間、類名稱空間內定義了兩個 lambda 表示式,在全域性空間內定義的 lambda 表示式就相當於一個普通函數,因此程式使用呼叫函數的方式來呼叫該 lambda 表示式,並顯式地為第一個引數系結引數值,如上面程式中 ① 號程式碼所示。

對於在類名稱空間內定義的 lambda 表示式,則相當於在該類名稱空間中定義了一個函數,這個函數就變成了實體方法,因此程式必須使用呼叫方法的方式來呼叫該 lambda 表示式,Python 同樣會為該方法的第一個引數(相當於 self 引數)係結引數值,如上面程式中 ② 號程式碼所示。