10.高階函數、閉包和裝飾器

1.高階函數

  • 接收函數作爲參數
# 高階函數——接收函數作爲參數,或接收函數作爲返回值
# 定義一個函數將列表中所有的偶數保存到一個新的列表中

lst1 = [1, 2, 3, 4, 5, 6, 7, 8]
# 高階函數
# 函數作爲參數——此時就是將一段代碼傳遞到函數中啦
# 檢查奇偶、是否大於3
def fn1(i):
    if i % 2 == 0:
        return True
def fn2(i):
    if i % 2 != 0:
        return True
def fn3(i):
    if i > 3:
        return True

def fn(func, lst):
    new_list = []
    # 遍歷
    for i in lst:
        # 判斷 調用函數——注意這裏時函數調用不是函數對象
        if func(i):
            new_list.append(i)
    # 返回
    return new_list
s = fn(fn3, lst1)
print(s)
  • 將函數作爲返回值返回

1.1 匿名函數

'''
filter(func, lst)可以從序列裏過濾出符合條件的元素,保存到一個新的序列中
參數一func 這是一個函數對象,根據這個函數來過濾
參數二lst  這是一個序列,是需要進行過濾的對象
返回值     這是過濾後產生的新序列
'''

lst = [1, 2, 3, 6, 5, 9, 12]
def fn1(i):

    if i % 3 == 0:
        return True

    return False

# def fn(func, lst):
#     new_lst = []
#     for i in lst:
#         if fn1(i):
#             new_lst.append(i)
#     return new_lst
# print(fn(fn1, lst))
s = list(filter(fn1, lst))
print(s)

# 匿名函數 lambda 函數表達式
# lambda函數表達式專門用來創建一些簡單的函數,是函數的另一種表達方式
# 語法:lambda 參數列表:返回值

# 常規函數
def fm(a, b):
    return a + b
# 匿名函數
fm1 = lambda a,b: a + b
print(s(1, 2))

2.閉包

  • 將函數作爲返回值返回的高階函數我們又稱之爲閉包
# 高階函數
# 以函數作爲返回值,又稱爲閉包
# 通過閉包可以創建一些只有當前函數可以訪問的變量 a
# 可以將一些私有的變量藏到閉包中

def fn():
    a = 123
    def fn1():
        print('我是fn1...', a)
    return fn1

s = fn()
print(s)    # <function fn.<locals>.fn1 at 0x0000000002880620>

print(s())  # 我是fn1... 123
            # None

s()         # 我是fn1... 123

print(a)    # NameError: name 'a' is not defined
  • 閉包的好處
    。通過閉包可以創建一些只有當前函數可以訪問的變量
    。可以將一些私有數據藏到閉包中

  • 形成閉包的條件
    。函數嵌套
    。將內部函數作爲返回值返回
    。內部函數必須要使用到外部函數的變量

# 求列表中元素的平均值
# nums = [4, 4, 6, 3, 7, 8, 9]
# print(sum(nums) / len(nums))

# 定義一個函數求平均值

# 我不成熟的寫法
# nums = [4, 4, 6, 3, 7, 8, 9]
# def average(nums):
#
#     return sum(nums) / len(nums)
#
# print(average(nums))

# 老師的寫法
# nums = [] 寫在全局時容易被修改
# 閉包三條件,缺一不可:
# 閉包——函數嵌套
# 閉包——內部函數作爲返回值
# 閉包——內部函數用到外部函數的變量

def make_average():

    nums = []

    def average(n):

        nums.append(n)

        return sum(nums) / len(nums)
    # print(average(10))  # 10.0
    # print(average(5))   # 7.5
    return average

fn = make_average()
print(fn(10))   # 10.0
print(fn(5))    # 7.5

3.裝飾器的引入

  • 我們可以直接修改函數中的代碼來滿足要求,但是往往伴隨以下問題:
    。如果修改的函數比較多,就比較麻煩
    。不方便後期維護
    。違反開閉原則ocp(程序設計要求開發對程序的擴展,關閉對程序的修改)

4.裝飾器的使用

  • 通過裝飾器可以在不修改原來函數的情況下,對函數進行修改
  • 在開發中,我們都是通過裝飾器來擴展函數的功能的

# 裝飾器 —— 類似於start_end(old)這種不用對原函數修改就能對其功能進行擴展的函數
def start_end(old):
    # 創建一個新的函數
    def new_function(*args,**kwargs):
        print('開始執行..')
        # fn()
        r=old(*args,**kwargs)
        print('執行結束..')
        return r

    return new_function
# 裝飾器的寫法
@start_end
def speak():
    print('同學們好好複習啊')
speak()

@start_end
def fn():
    print('我是fn函數')
fn()

@start_end
def add(a,b):
    r = a+b
    return r
r=add(123,123)
print(r)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章