电竞比分网-中国电竞赛事及体育赛事平台

分享

Python教程:函數式編程

 copy_left 2023-06-24 發(fā)布于四川
Python函數式編程是一種編程范式,它強調使用純函數來處理數據。函數是程序的基本構建塊,并且盡可能避免或最小化可變狀態(tài)和副作用。在函數式編程中,函數被視為一等公民,可以像值一樣傳遞和存儲。本教程將介紹如何使用Python進行函數式編程,并提供一些示例。
圖片
python函數式編程

1.純函數

純函數是指不產生副作用的函數,即只依賴于輸入參數并返回輸出結果,而不修改任何外部狀態(tài)。純函數通常易于測試、可組合和并發(fā)執(zhí)行。例如,下面是一個非純函數:

total = 0

def add(n):
    global total
    total += n
    return total

這個函數會修改total全局變量,因此是有副作用的。相反,下面是一個純函數:

def add(n):
    return n + 1

這個函數只依賴于輸入參數并返回輸出結果,沒有任何副作用。

2.函數是一等公民

在函數式編程中,函數是一等公民。這意味著函數可以像其他數據類型一樣傳遞給其他函數,也可以從其他函數中返回。例如:

def apply(func, arg):
    return func(arg)

def double(x):
    return x * 2

print(apply(double, 5)) # 輸出 10

在這個例子中,我們定義了一個名為apply的函數,它接受兩個參數:一個函數和一個參數。它將這個參數傳遞給這個函數并返回結果。

3.高階函數

高階函數是指接受一個或多個函數作為參數和/或返回一個函數的函數。Python提供了許多內置的高階函數,如map,filterreduce。例如:

# map
def square(x):
    return x ** 2

numbers = [1, 2, 3, 4, 5]
squares = list(map(square, numbers))
print(squares) # 輸出 [1, 4, 9, 16, 25]

# filter
def is_even(x):
    return x % 2 == 0

numbers = [1, 2, 3, 4, 5]
evens = list(filter(is_even, numbers))
print(evens) # 輸出 [2, 4]

# reduce
from functools import reduce

def add(x, y):
    return x + y

numbers = [1, 2, 3, 4, 5]
sum = reduce(add, numbers)
print(sum) # 輸出 15

在這個例子中,我們定義了三個函數:square,is_evenadd。然后,我們使用內置的高階函數map,filterreduce來對數字列表進行操作。

4.Lambda表達式

Lambda表達式是一種匿名函數,可以用來定義簡單的函數。它們通常在需要一個函數作為參數的地方使用。例如:

numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # 輸出 [1, 4, 9, 16, 25]

evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # 輸出 [2, 4]

在這個例子中,我們使用Lambda表達式來定義mapfilter函數的函數參數。

更多教程:PoyCode編程指南[1]

5.偏函數

偏函數是指通過部分設置參數來創(chuàng)建新函數的過程。在Python中,我們可以使用functools.partial函數來實現(xiàn)偏函數。偏函數是一種指定部分參數的函數。例如,假設有一個函數:

def power(base, exponent):
    return base ** exponent

如果要計算2的平方和立方,可以這樣實現(xiàn):

print(power(2, 2))
print(power(2, 3))

輸出:

4
8

使用偏函數可以更方便地計算多個指數。例如:

from functools import partial

square = partial(power, exponent=2)
cube = partial(power, exponent=3)

print(square(2))
print(cube(2))

輸出:

4
8

這里使用了functools.partial函數將power函數的exponent參數固定為23,從而創(chuàng)建了兩個新的函數squarecube。

6.函數組合

函數組合是指將多個函數組合成一個函數。例如,假設有兩個函數:

def add1(n):
    return n + 1

def double(n):
    return n * 2

現(xiàn)在要實現(xiàn)一個新函數,將add1double組合起來,可以這樣實現(xiàn):

def compose(f, g):
    return lambda x: f(g(x))

add1_double = compose(add1, double)
print(add1_double(3))

輸出:

7

這個函數首先將輸入參數3傳遞給double函數,然后將其結果6傳遞給add1函數,最終得到7。

上一篇教程:Python數據結構:列表、元組、字典、集合[2]

7.不可變性

函數式編程鼓勵不可變性,盡量減少或避免可變狀態(tài)和副作用。這可以通過使用元組、凍結集合和不可變對象來實現(xiàn)。例如:

# 元組
person = ('John', 25)
name, age = person

# 凍結集合
my_set = frozenset([1, 2, 3])

# 不可變對象
from collections import namedtuple

Person = namedtuple('Person', ['name', 'age'])
person = Person(name='John', age=25)

在這個例子中,我們使用元組、凍結集合和不可變對象來創(chuàng)建不可變數據結構。

8. 尾遞歸優(yōu)化

尾遞歸是指函數的最后一個操作是它自己的遞歸調用。這可以通過迭代實現(xiàn),并且可以避免堆棧溢出錯誤。Python沒有尾遞歸優(yōu)化,但可以使用生成器和迭代器來模擬。尾遞歸優(yōu)化是一種技術,它可以將遞歸函數的調用棧優(yōu)化為迭代循環(huán),從而減少內存占用和提高程序性能。

在 Python 中實現(xiàn)尾遞歸優(yōu)化有兩種方法:

  1. 1. 使用 sys.setrecursionlimit() 函數增加最大遞歸深度。

  2. 2. 實現(xiàn)一個尾遞歸函數,并使用一個 while 循環(huán)替換遞歸調用。

以下是一個簡單的例子:

import sys

sys.setrecursionlimit(10000)

def factorial(n, acc=1):
    if n == 0:
        return acc
    else:
        return factorial(n-1, acc*n)

def tail_recursion_factorial(n, acc=1):
    while n > 0:
        n, acc = n-1, acc*n
    return acc

在這個例子中,我們定義了兩個函數:factorial 和 tail_recursion_factorial。factorial 是一個正常的遞歸函數,而 tail_recursion_factorial是一個尾遞歸函數。

如果使用 factorial(1000) 這樣的參數調用 factorial 函數,將會產生 RecursionError,因為默認情況下 Python 的最大遞歸深度為1000。為了解決這個問題,我們增加了最大遞歸深度并重新運行代碼。

使用 tail_recursion_factorial(1000) 來調用 tail_recursion_factorial 函數,則不會出現(xiàn)RecursionError,因為該函數被優(yōu)化為迭代循環(huán)。

需要注意的是,尾遞歸優(yōu)化并不總是有效,因為有時候需要保留函數調用棧以便于在返回時執(zhí)行一些操作。此外,在 Python 中默認情況下并沒有進行尾遞歸優(yōu)化,因此需要手動實現(xiàn)它。

圖片
python函數式編程

9.總結

Python函數式編程是一種編程范式,它的核心思想是將計算視為數學函數的運算,并且避免使用可變狀態(tài)和副作用。

第一步是理解函數是什么。在函數式編程中,函數被認為是“一等公民”,這意味著它們可以像任何其他數據類型一樣傳遞和操作。因此,函數通常會接受輸入并返回輸出,而不會修改狀態(tài)或影響外部環(huán)境。

然后,我們需要了解Python中的lambda表達式。Lambda表達式是一種匿名函數,它可以在需要時方便地定義和調用。它的語法類似于“l(fā)ambda arguments: expression”,其中arguments是參數列表,expression是函數體。

接下來是高階函數。在函數式編程中,高階函數是指接受一個或多個函數作為參數的函數,或者返回一個新函數的函數。例如,map()函數可以接受一個函數和一個序列,并返回一個新序列,其中每個元素都是通過應用給定函數得到的結果。

還有一個重要的概念是閉包。閉包是指一個函數內部定義的函數,它可以訪問其外部函數的變量和參數。這使得我們可以創(chuàng)建一些特殊的函數,例如currying和partial functions。

此外,函數式編程還涉及到一些常見的函數,例如filter()、reduce()和sorted()。這些函數可以幫助我們在Python中進行函數式編程。

最后,我們需要了解如何避免使用可變狀態(tài)和副作用。這意味著我們應該盡可能避免修改對象的狀態(tài)或影響外部環(huán)境。相反,我們應該嘗試編寫純函數,這些函數只依賴于其輸入,并且不會修改狀態(tài)或引起副作用。

總之,在Python中進行函數式編程需要掌握lambda表達式、高階函數、閉包以及避免使用可變狀態(tài)和副作用等概念。通過這些技術,我們可以創(chuàng)建更具可讀性、可維護性和可重用性的代碼。

引用鏈接

[1] Poycode編程指南: http://www.
[2] Python數據結構:列表、元組、字典、集合: http://www./archives/169

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多