-
Notifications
You must be signed in to change notification settings - Fork 94
好的,以下是 第4章:純函數與不可變性 的內容草稿:
純函數和不可變性是函數式編程的兩個核心概念。這些概念不僅有助於提升代碼的可預測性和可測試性,還能降低程序中的副作用,從而使代碼更加穩定和可維護。
純函數(Pure Function)指的是一類具有以下特徵的函數:
- 相同的輸入永遠會得到相同的輸出:純函數不依賴於外部的狀態或變量,它的輸出僅取決於它的輸入。
- 沒有副作用:純函數不會修改任何外部狀態,也不會對程序其他部分產生影響。
# 純函數範例
def add(x, y):
return x + yadd 函數是純函數,因為對於相同的輸入,它始終會產生相同的輸出,並且沒有修改外部的狀態。
# 非純函數範例
total = 0
def add_to_total(x):
global total
total += x
return totaladd_to_total 函數不是純函數,因為它依賴於外部變量 total,並且每次調用都會修改這個變量的值,因此相同的輸入可能會產生不同的輸出。
使用純函數有許多優點:
- 可預測性:由於純函數始終對相同輸入給出相同的輸出,我們可以更容易地推斷和測試它的行為。
- 易於測試:純函數沒有副作用,因此測試時無需考慮外部狀態的變化。
- 易於並行處理:由於純函數不依賴共享狀態或修改外部狀態,這使得它們在多線程或並行處理中更加安全。
不可變性(Immutability)是函數式編程中的另一個關鍵概念。不可變性指的是一旦創建,數據結構的內容就不能被更改。與此相對的是可變性,它允許在不創建新對象的情況下修改對象的內容。
在 Python 中,一些內建的數據類型是不可變的,包括:
- 數字類型(如
int,float) - 字符串(
str) - 元組(
tuple)
# 不可變範例
x = 10
y = x
x = 20
print(y) # 結果仍然是 10,因為數字是不可變的可變對象如列表(list)或字典(dict),可以在原地修改,而不會創建新的對象:
# 可變對象範例
my_list = [1, 2, 3]
my_list.append(4)
print(my_list) # 結果為 [1, 2, 3, 4]不可變性的重要性在於它可以避免難以追踪的狀態變更問題,特別是在多線程或併發程序中。
雖然 Python 中的列表和字典是可變的,但我們可以通過一些方法來實現不可變性。
元組是不可變的數據結構,我們可以使用元組來代替列表,以保持不可變性。
# 使用 tuple 代替 list
my_tuple = (1, 2, 3)
# my_tuple[0] = 10 # 這行代碼會產生錯誤,因為元組是不可變的雖然 Python 沒有內建的不可變字典類型,但我們可以使用 types.MappingProxyType 來創建一個不可變的字典視圖。
from types import MappingProxyType
my_dict = {'a': 1, 'b': 2}
frozen_dict = MappingProxyType(my_dict)
# frozen_dict['a'] = 10 # 這行代碼會產生錯誤,因為 frozen_dict 是不可變的有一些第三方庫(如 pyrsistent)專門提供不可變的數據結構,可以方便地引入到 Python 的函數式編程中。
pip install pyrsistentfrom pyrsistent import pvector
immutable_list = pvector([1, 2, 3])
new_list = immutable_list.append(4)
print(immutable_list) # 結果仍然是 [1, 2, 3]
print(new_list) # 結果為 [1, 2, 3, 4]純函數和不可變性是函數式編程的基石。通過使用純函數,我們可以創建更容易理解、測試和維護的代碼。而不可變性則幫助我們避免難以追踪的狀態變化,尤其是在併發環境中。這兩個概念的結合,讓我們能夠寫出更安全、更健壯的代碼。
這是第4章的基本內容草稿,若有需要進一步擴展的部分,隨時可以提出!
從希爾伯特到圖靈的那些故事
-- 以 Python 展現這些故事背後的程式