目錄
一、普通函數
1.1 函數的定義與調用
1.2 函數的說明文檔
1.3?函數的參數
1.4?函數的返回值
二、函數的作用域和關鍵字
2.1 局部作用域
2.2 全局作用域
2.4?global關鍵字和nonlocal關鍵字的使用
三、函數的遞歸與嵌套
3.1 嵌套函數
3.2遞歸函數
四、函數名的應用
4.1 函數名可以作為另一個函數的參數或者返回值
4.2 函數名可以成為字典、集合、列表、元組中的元素
五、匿名函數與高階函數
5.1 匿名函數
5.2 高階函數
六、函數的閉包與裝飾器
6.1 閉包
6.2 裝飾器
一、普通函數
1.1 函數的定義與調用
定義:
def 函數名(參數):
? ? 函數體
? ? return 返回值
函數通過def關鍵字定義,def關鍵字后面跟著函數的函數名,函數名后面跟著小括號,小括號里面傳入函數需要的參數(函數可以有參數也可以沒有參數)。中間寫函數體,最后寫返回值(返回值可以有可以沒有,默認為None)。
1.2 函數的說明文檔
定義:函數說明文檔(docstring)是用來描述函數功能、參數、返回值等信息的字符串,直接寫在函數定義的第一行,使用三重引號 """ """
包裹。它可以幫助其他開發者快速理解函數的用途,也方便自動生成文檔。
使用內置函數help()可以查看函數的說明文檔、使用函數名.__doc__的方式也能夠查看。
示例:
def add(a, b):"""計算兩個數的和。參數:a (int or float): 第一個加數b (int or float): 第二個加數返回:int or float: 兩數之和"""return a + bhelp(add)
print(add.__doc__)
1.3?函數的參數
函數的參數有可變參數與不可變參數
不可變參數:位置參數、關鍵字參數、僅關鍵字參數、默認參數。
可變參數:可變位置參數(*args)、可變關鍵字參數(**kwargs)。
參數的定義順序為:位置參數-->關鍵字參數-->可變位置參數(*args)-->僅關鍵字參數-->可變關鍵字參數(**kwargs)
1.4?函數的返回值
函數的返回值可以有多個(當有多個返回值時,會自動打包成元組),也可以沒有返回值,返回值默認為None
二、函數的作用域和關鍵字
函數作用域遵循以下規則:Python 按 LEGB 順序查找變量:Local(局部作用域)→ Enclosing(閉包作用域) → Global(全局作用域) → Built-in(內置作用域)。
2.1 局部作用域
定義在函數內的變量稱為局部變量,該變量只能在局部作用域中訪問和修改。
2.2 全局作用域
定義在函數外的變量稱為全局變量,該變量可以在任意作用域中訪問。
2.3 可變類型與不可變類型
可變類型:指的是在對某一可變類型進行修改時不會隨著修改而改變內存地址的,即對象本身不變。(可變類型有:列表,字典,集合)
不可變類型:該對象在內存中的地址固定,一旦確定了將不會發生改變,如果對該對象進行修改則會改變它在內存中的地址。(不可變類型有:字符串,元組,數值類型,布爾類型)
可變類型與不可變類型在函數作用域的影響:我們都知道,在局部作用域中如果不使用global關鍵字聲明的話就只能對對象進行訪問不能進行修改,如果該對象是一個可變類型的,那么我們在局部作用域中也能夠對該對象進行訪問和修改的操作(這里的修改不是改變該對象本身)
2.4?global關鍵字和nonlocal關鍵字的使用
global關鍵字:
如果想通過局部作用域來修改全局變量的話,那么就需要使用global關鍵字來聲明。被global關鍵字聲明的變量可以在局部作用域中被修改(未聲明的變量只能訪問)。
示例:
使用global:在函數內部,如果想要修改函數外部(全局作用域)定義的變量,必須使用 global 關鍵字聲明該變量。x = 10 # 全局變量def modify():global x # 聲明x是全局變量x = 20 # 修改全局變量xmodify() print(x) # 輸出 20
不使用global:如果沒有使用 global,函數內部對同名變量的賦值會創建一個新的局部變量,不會影響全局變量。
x = 10def modify():x = 20 # 這里創建了一個局部變量x,和全局變量無關modify() print(x) # 輸出 10,未被修改
nonlocal關鍵字:
nonlocal 用于在嵌套函數中聲明變量,表示該變量不是當前函數的局部變量,而是外層(但不是全局)函數作用域中的變量。這樣,內層函數就可以修改外層函數中的變量。
示例:多層嵌套
def outer():x = 10def middle():nonlocal xdef inner():nonlocal xx = 30inner()middle()print(x) # 輸出 30outer()
三、函數的遞歸與嵌套
3.1 嵌套函數
定義:在一個函數內部定義另一個函數,或者在函數內部調用另一個函數,滿足其中任意一個條件即稱為嵌套函數。
示例:inner_function 是定義在 outer_function 內部的嵌套函數,outer_function 內部調用了 inner_function。
def outer_function(x):def inner_function(y):return y * yreturn inner_function(x) + 1print(outer_function(3)) # 輸出 10,因為 3*3+1=10
3.2遞歸函數
定義:遞歸函數就是函數自己調用自己
注意事項:在使用遞歸函數的時候要給遞歸函數設置一個出口,否則函數會一直執行下去直到棧溢出。
示例:factorial 函數通過遞歸計算階乘,if n == 0 是遞歸出口,防止無限遞歸。
def factorial(n):if n == 0: # 遞歸出口return 1else:return n * factorial(n - 1) # 函數自己調用自己print(factorial(5)) # 輸出 120
四、函數名的應用
4.1 函數名可以作為另一個函數的參數或者返回值
示例:函數名本質上是指向函數對象的引用,可以作為參數傳遞給其他函數,也可以作為函數的返回值返回。
def greet():return "Hello!"def call_func(func):return func() # 調用傳入的函數result = call_func(greet)
print(result) # 輸出:Hello!def get_greet_func():return greet # 返回函數對象f = get_greet_func()
print(f()) # 輸出:Hello!
4.2 函數名可以成為字典、集合、列表、元組中的元素
示例:函數名作為函數對象,可以存儲在各種數據結構中,便于動態調用。
def add(x, y):return x + ydef multiply(x, y):return x * yfunc_list = [add, multiply]
print(func_list[0](2, 3)) # 輸出:5
print(func_list[1](2, 3)) # 輸出:6func_dict = {'加法': add, '乘法': multiply}
print(func_dict['加法'](4, 5)) # 輸出:9func_tuple = (add, multiply)
print(func_tuple[1](3, 7)) # 輸出:21func_set = {add, multiply}
for f in func_set:print(f(1, 2)) # 依次輸出3和2(順序不確定)
五、匿名函數與高階函數
5.1 匿名函數
匿名函數指的是只用一串代碼就能定義的函數,使用lambda關鍵字聲明。
語法:lambda 參數:函數體+返回值(函數體就是返回值,返回值就是函數體)
應用場景:對一些比較簡單的函數的創建與使用,作為高階函數中的參數,對一些只使用一次的簡單函數的創建。
示例:
# 普通函數定義
def add(x, y):return x + yprint(add(3, 5)) # 輸出 8# 使用匿名函數
add_lambda = lambda x, y: x + y
print(add_lambda(3, 5)) # 輸出 8# 作為高階函數參數
numbers = [1, 2, 3, 4, 5]# 用lambda對列表元素平方
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # 輸出 [1, 4, 9, 16, 25]# 用lambda篩選偶數
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # 輸出 [2, 4]# 用lambda排序,根據字符串長度排序
words = ['apple', 'banana', 'pear', 'grape']
words_sorted = sorted(words, key=lambda s: len(s))
print(words_sorted) # 輸出 ['pear', 'grape', 'apple', 'banana']
5.2 高階函數
定義:一個函數如果他的參數中有函數名,或者是他的返回值有函數名就可以被稱為高階函數
常見的高階函數有:
1、map(function, iterable)?
參數:第一個參數為函數,第二個參數為可迭代對象
返回值:返回一個迭代器對象
作用:對可迭代對象中的每個元素執行指定函數。返回一個新的迭代器(返回結果為該迭代器的內存地址)
2、reduce(function, iterable[, initializer])
參數:第一個參數為函數,第二個參數為可迭代對象。initializer用于指定計的初始值。
- 如果指定了 initializer,累計時的第一個調用會用 initializer 和可迭代對象的第一個元素作為參數調用 function。
- 如果不指定,reduce 會用可迭代對象的前兩個元素作為第一次調用的參數,累計結果從第一個元素開始。
返回值:返回一個數值型對象。
作用:對可迭代對象的元素累計執行函數(函數必須接收兩個參數),將函數返回的結果與下一個元素做累積處理,最終返回單一值。
示例:
?
from functools import reduce# 計算列表元素之和
result = reduce(lambda x, y: x + y, [1, 2, 3, 4], 10)
print(result) # 輸出 20,因為初始值是 10,累計結果是 10+1+2+3+4=20?
3、filter(function, iterable)
參數:第一個參數是一個函數,第二個參數是可迭代對象
作用:根據函數定義的規則過濾可迭代對象,保留函數返回值為True的元素,返回一個過濾后的迭代器對象。
返回值:返回一個迭代器對象
4、sorted(iterable, *, key=None, reverse=False)
參數:第一個參數為可迭代對象,第二個參數為‘*’目的是為了使key和reverse變為僅關鍵字參數,key是一個函數用于指定排序規則,默認為None。reverse為False時為升序排序,為True時為降序排序。
返回值:返回一個列表。
作用:對可迭代對象排序,按照key所定義的規則,返回一個新的列表。
示例:
# 對數字列表升序排序(默認)
print(sorted([3, 1, 4, 2])) # 輸出 [1, 2, 3, 4]# 對數字列表降序排序
print(sorted([3, 1, 4, 2], reverse=True)) # 輸出 [4, 3, 2, 1]# 根據字符串長度排序
words = ['apple', 'banana', 'cherry', 'date']
print(sorted(words, key=len)) # 輸出 ['date', 'apple', 'banana', 'cherry']
5、zip(*iterables, strict=False)
參數:第一個參數為任意數量的可迭代對象,第二個參數strict默認為False
- 如果為 False(默認),zip 會以最短的可迭代對象長度為準,生成對應數量的元組,超出部分會被忽略。
- 如果為 True,則要求所有可迭代對象長度相同,否則會拋出 ValueError 異常。
返回值:返回一個迭代器對象
作用:合并參數一中的可迭代對象,參數二默認值為False,當strict為True時,要求每個可迭代對象的元素個數要一樣多,否則發生報錯。
6、enumerate(iterable, start=0)
參數:第一個參數是可迭代對象,第二個參數是指定索引起始值,默認從 0 開始計數。可以設置為任意整數。
返回值:返回一個迭代器對象
作用:可迭代對象進行遍歷時,同時獲取元素的索引(序號)和元素本身。返回一個枚舉對象(迭代器),其中每個元素是一個由索引和值組成的元組。
高階函數應用場景:
六、函數的閉包與裝飾器
6.1 閉包
定義:一個前提兩個條件,滿足就為閉包。在嵌套函數中,內部函數使用了外部函數的參數并且內部函數的返回值為外部函數的函數名,那么就把這個使用了外部函數參數的內部函數稱為閉包。
閉包的作用:我們都知道,當一個函數執行結束時,函數內部的變量都將被銷毀。如果使用了閉包,那么該函數執行結束將不會被銷毀,并且在全局作用域中可以通過閉包間接訪問局部變量。
示例:
def outer(x):def inner(y):return x + y # 內部函數使用了外部函數的參數xreturn inner # 返回內部函數f = outer(10) # f是inner函數的閉包,記住了x=10
print(f(5)) # 輸出 15
6.2 裝飾器
定義和作用:裝飾器(Decorator)是一種特殊的函數它接受一個函數作為參數,并返回一個新的函數。它的主要作用是在不修改被裝飾函數的源代碼和調用方式的前提下,為函數增加額外功能(裝飾器的本質是:高階函數+閉包)
裝飾器的基本語法:使用語法糖@后面跟上裝飾器的函數名。在函數定義時裝飾需要被裝飾的函數。
def decorator(func):def wrapper():# 在調用原函數前可以做一些操作print("開始執行函數")func()# 在調用原函數后可以做一些操作print("函數執行完畢")return wrapper@decorator # 語法糖,等同于 foo = decorator(foo)
def foo():print("這是被裝飾的函數")foo()
"""
輸出:
復制
開始執行函數
這是被裝飾的函數
函數執行完畢
"""
應用場景:
日志記錄:在函數執行前后打印日志信息
權限校驗:在函數執行前檢查用戶權限
性能測試:計算函數執行時間
緩存:保存函數的計算結果,避免重復計算