1. 程式人生 > 其它 >Python語言之高階函式

Python語言之高階函式

Python語言之高階函式

前言

人生苦短,我用Python。

一、閉包

Python函式是支援巢狀的。如果在一個內部函式中對外部函式作用域(非全域性作用域)的變數進行引用,那麼內部函式就會被稱為閉包。閉包需要滿足如下3個條件:

  • 存在於兩個巢狀關係的函式中,並且閉包是內部函式;

  • 內部函式引用了外部函式的變數(自由變數);

  • 外部函式會把內部函式的函式名稱返回。(不帶括號)

def nth_power(exponent):
    def exponent_of(base):
        return base ** exponent
    return exponent_of # 返回值是 exponent_of 函式


square = nth_power(2) # 計算一個數的平方,傳遞exponent為2
cube = nth_power(3) # 計算一個數的立方,傳遞exponent為3
print(square(2))  # 計算 2 的平方,傳遞base為2
print(cube(2)) # 計算 2 的立方,傳遞base為2
print(nth_power(2)(4))# 直接計算 2 的4次方

為什麼使用閉包?

引用資料:

二、裝飾器

裝飾器的概念

假設我們已經開發了一個本有的函式,後續可能會增加臨時的需求,例如插入日誌,我們可以增加一個包裹函式,由它來負責這些額外的需求,這個包裹函式就是裝飾器 。

裝飾器主要應用在如下場景:

  • 引入日誌;
  • 函式執行時間統計;
  • 執行函式前預備處理;
  • 執行函式後清理功能;
  • 許可權校驗;
  • 快取。

裝飾器是一個函式,它需要接收一個被修飾的函式作為引數。例如,有如下一個裝飾器函式:

def w1(func):
    print('正在裝飾')
    def inner():
        print('正在驗證許可權')
        func()
    return inner
  • 裝飾器是個巢狀函式

  • 內部函式是一個閉包

  • 外部函式接收的是被修飾的函式(func)

通過在函式定義的前面新增@符號和裝飾器名,實現裝飾器對函式的包裝。給f1函式加上裝飾器,示例如下:

@w1
def f1():
    print('f1')

呼叫f1時候,程式會自動編譯生成呼叫裝飾器函式的程式碼,等價於:

f1 = w1(f1)

多個裝飾器

多個裝飾器應用在一個函式上,是一個巢狀的關係,呼叫順序是從下至上,再從上至下。

def w1(func):
    print('正在裝飾w1')
    def inner():
        print('正在驗證許可權w1')
        func()
    return inner
def w2(func):
    print('正在裝飾w2')
    def inner2():
        print('正在驗證許可權w2')
        func()
    return inner2
@w1
@w2
def f1():
    print('f')
#f1() #先註釋掉,觀察執行結果
#相當於w1(w2(f1))()

裝飾有引數的函式

def w1(func):
    def inner(a,b):
       print('開始驗證許可權')
       func(a,b)
    return inner


@w1
def test(a,b):
    print('a=%d,b=%d'%(a,b))
test(1,2)

裝飾帶有返回值的函式

def func(functionName):
    print('進入裝飾器')
    def func_in():
        print('呼叫被裝飾函式')
        return functionName()
    return func_in
@func
def test():
    return 'itheima'
print(test())

帶有引數的裝飾器

如果給裝飾器新增引數,需要增加一層包裝,先傳遞引數,然後再傳遞函式名。示例程式碼如下:

def func_arg(args):
    def func(functionName):
        def func_in():
            print('記錄日誌:%s'%args)
            functionName()
        return func_in
    return func


@func_arg('這是一條日誌')
def fun1():
    print('記錄完成')
fun1()

三、裝飾器常見Python內建函式

map函式

map函式會根據提供的函式對指定的序列做對映。

map函式的定義如下:

map(function, iterable,…)

第1個引數是函式的名稱;第2個引數表示支援迭代的容器或者迭代器。

map函式的作用是以引數序列中的每個元素分別呼叫function函式,把每次呼叫後返回的結果儲存為物件。

func = lambda x:x+2
result = map(func, [1,2,3,4,5])
print(list(result))

執行過程:

filter函式

filter函式會對指定序列執行過濾操作。

filter函式的定義如下:

filter(function,iterable)

第1個引數可以是函式的名稱;第2個引數表示的是序列、支援迭代的容器或迭代器。

func = lambda x:x%2
result = filter(func, [1, 2, 3, 4, 5])
print(list(result))

執行過程:

reduce函式

reduce函式會對引數序列中的元素進行迭代運算。

reduce函式的定義如下:

reduce(function, iterable[, initializer])
  • function是一個帶有兩個引數的函式;
  • iterable是一個可迭代物件;
  • initializer表示固定的初始值。

函式將一個數據集合(連結串列,元組等)中的所有資料進行下列操作:用傳給 reduce 中的函式 function(有兩個引數)先對集合中的第 1、2 個元素進行操作,得到的結果再與第三個資料用 function 函式運算,最後得到一個結果。

reduce(function, iterable[, initializer])
from functools import reduce
func = lambda x,y:x+y
result = reduce(func, [1, 2, 3, 4, 5])
print(result)

注意:function函式不能為None。

在Python 3中,reduce函式已經被從全域性名字空間裡面移除了,它現在被放置在fucntools模組中,使用時需要先引入,格式如下:

from functools import reduce

結尾