Python入門 函數 提高篇
一、變數作用域
Python 中,程序的變數並不是在哪個位置都可以訪問的,在哪裡賦值決定了該變數的作用域。
Python的作用域一共有4種,分別是:
L (Local) 局部作用域
E (Enclosing) 閉包函數外的函數中G (Global) 全局作用域B (Built-in) 內建作用域
變數的查找以 L –> E –> G –>B 的規則查找,即:在局部找不到,便會去局部外的局部找(例如閉包),再找不到就會去全局找,再者去內建中找。
Python 中只有模塊(module),類(class)以及函數(def、lambda)才會引入新的作用域,其它的代碼塊(如 if/elif/else/、try/except、for/while等)是不會引入新的作用域的,也就是說這這些語句內定義的變數,外部也可以訪問。
示例:
if True:n ifmsg = I am ifmsgnprint(ifmsg) # 可以在if外面訪問msgnndef fun():n funmsg = I am funmsgnprint(funmsg) # 不可以在函數外訪問函數中的定義的變數n
1、全局變數和局部變數
定義在函數內部的變數擁有一個局部作用域,定義在函數外的擁有全局作用域。
局部變數只能在其被聲明的函數內部訪問,而全局變數可以在整個程序範圍內訪問。調用函數時,所有在函數內聲明的變數名稱都將被加入到作用域中。
示例:
total = 0 # 這是一個全局變數ntotal2 = 5ndef sum(arg1, arg2):n print(total2) # 我們可以在函數體類訪問全局變數,訪問後不能對total2賦值n total = arg1 + arg2 # total在這裡是局部變數n print("函數內是局部變數total : ", total)n return totalnn# 調用sum函數nsum(10, 20)nprint("函數外是全局變數total : ", total)n
輸出結果:
5
函數內是局部變數total : 30函數外是全局變數total : 0
注意:第4行print(total2)訪問了total2,訪問後我不能在對total2賦值; 第5行total = arg1 + arg2我們在函數內改變了total的值,total成為了函數內的局部變數,它並不會影響全局變數total 的值。
2、global 和 nonlocal關鍵字(了解)
當內部作用域想修改外部作用域的變數時,就要用到global和nonlocal關鍵字了。
示例:
num = 123nndef fun1():n global num # 使用 global 關鍵字聲明,使num全局變數值可在函數內修改n print(num)n num = 456 # 修改全局變數值nnfun1()nprint(num) # 結果 456,全局變數值被修改n
輸出結果
1
123123
如果要修改嵌套作用域(enclosing 作用域,外層非全局作用域)中的變數則需要 nonlocal 關鍵字了
示例:
def out():n num = 10 # out內部變數n def inner():n nonlocal num # nonlocal關鍵字聲明n print(num)n num = 100 # 修改out內部變數n inner()n print(num)nout()n
輸出結果:
10
100
二、匿名函數 lambda
lambda 匿名函數,他是一種比def更簡單的函數,該函數的定義邏輯非常簡單,函數體只能有一個表達式,返回結果為表達式的值。
1、lambda 匿名函數定義
lambda [參數1[,參數2,.....參數n]]:表達式
實例:
g = lambda x:x*x+1nprint(g(1)) # 結果為2nprint(g(3)) # 結果為10n
釋:可以這樣認為,lambda作為一個表達式,定義了一個匿名函數,上例的代碼x為入口參數,x*x+1為函數體,用函數來表示為:
def g(x):n return x*x+1n
非常容易理解,在這裡lambda簡化了函數定義的書寫形式。是代碼更為簡潔,但是使用函數的定義方式更為直觀,易理解。
2、lambda 匿名函數的 if...else..
lambda expression1 if condition else expression2
釋義:如果condition 為True,條件表達式的結果為expression1,否則為expression2
示例:
funmax = lambda x, y: x if x > y else y # 求兩個數最大值n# 如果 x>y 則返回x,否則返回ynprint(funmax(5, 6))nn# 遞歸求n!nfunc = lambda n: 1 if n == 0 else n * func(n - 1)nprint(func(5))n
注意:lambda 並不會給程序運行效率的提高,只會使代碼簡潔些,非常簡單的函數可以使用lambda。 如果需要使用到for...in...或if...else... ,最好不用lambda,它對代碼的可讀性和可重用性影響很大。 複雜的lambda是逗B用來炫技的。
3、lambda 匿名函數靈活運用
lambda 匿名函數使Python3的有些類和函數使用更加靈活。如:filter, map, reduce
filter(function,sequence)
過濾篩選類,他能過濾篩選序列中的數據,Python2返回list列表,Python3返回可迭代對象。
map(function,sequence)
將function調用映射到每個序列的對應元素上,Python2返回所有值的列表,Python3返回可迭代對象。
reduce(function,sequence,[initial])
累積函數,function有兩個參數,如無initial值,取sequence第一個元素與第二個為function參數,有則initial值作為第一個參數,sequence的第一個參數作為第二個參數。function返回值作為下次調用的第一個參數,取sequence中沒選取的後一個參數作為函數第二個參數,依次類推將結果積累返回。
示例:
list1 = [1, 18, 9, 7, 17, 12, 6]nf = filter(lambda x: x % 2 == 0, list1) # 篩選list1中能被2整除的數據,返回值可迭代對象nprint(list(f)) # 轉換為list 列印出結果nnm = map(lambda x: x * 2 + 10, list1) # 對list中的每個值進行操作,返回可迭代對象nprint(list(m))nnfrom functools import reducennr = reduce(lambda x, y: x + y, list1) # 對list中元素進行累積,相當於((((((1+18)+9)+7)+17)+12)+6)nprint(r)nnr = reduce(lambda x, y: x + y, list1, 1) # 對list中元素進行累積,初始值為1,相當於 1+((((((1+18)+9)+7)+17)+12)+6)nprint(r)n
輸出結果:
[18, 12, 6]
[12, 46, 28, 24, 44, 34, 22]7071
三、Python函數的可變參數(*args, **kwargs)
如果想讓一個函數能接受任意個參數,我們就可以定義一個可變參數。可變參數有序列可變與關鍵字可變。
1、*args 序列可變參數
序列可變參數定義格式如下:
def 函數名([參數,] *args):n 函數體n return [返回值]n
釋:args加了星號(*)的參數名會存放所有未命名的不帶鍵的參數,將這些參數轉換為一個元組存儲在args中。我們選擇傳入0~n個不帶鍵的參數。
注意:序列可變參數中的args傳入參數可以是元組或列表,也可以只不帶關鍵字的任意多個參數。
示例:
def variablefun(name, *args):n print(name, end=:)n for arg in args:n print(arg, end=,)n print()nnvariablefun(Bobo) # 可變參數可以不傳入值nvariablefun(woodman, 80, 90, man) # 可變參數可以傳入任意值ntuple1 = (女, 20)n# 元組或列表前無*可變參數將元組當成一個變數nvariablefun(Helen, tuple1)n# 元組或列表前有信號,可變參數將元組中的值當成了多個參數nvariablefun(Baby, *tuple1) # 注意觀察結果和Helen 的區別nvariablefun(Baby, 女, 20) # 加『*』 相當於傳入兩個值n
輸出結果:
Bobo:
woodman:80,90,man,Helen:(女, 20),Baby:女,20,Baby:女,20,
注意:第7、8行 說明可變參數可以傳入任意值;第11行調用函數variablefun(Helen, tuple1),傳入的是整個元組,函數會認為是一個元組參數 (女, 20);第13行variablefun(Baby, *tuple1)傳入參數元組前加了星號,程序會將元組數據拆開,按照順序傳入數據,*tuple1 傳入的是兩個參數『女』和 20 。
2、**kwargs 鍵對值可變型參數
序列可變參數定義格式如下:
def 函數名([參數,] **kwargs ):n 函數體n return [返回值]n
釋:kwargs 加了星號(**)的參數名會存放所有未命名的帶有鍵對值的變數參數,將這些參數轉換為一個字典存儲在kwargs 中。我們選擇傳入0~n個帶有鍵值對的參數。
注意:鍵對值可變參數中的kwargs 傳入參數可以是字典,也可以是任意帶關鍵字的參數。
示例:
def fun(name, **kwargs):n print(name:, name)n for key, value in kwargs.items():n print(key, :, value)n print(----------)nnfun(woodman) # 可變參數可以不傳入值nfun(Bob, sex=男) # 不在參數列表中的參數必須指定鍵值對ntuple1 = {sex: 男, class: 2016012}nfun(Alan, **tuple1) # 可以傳入字典,不要忘記**ntuple2 = {name: Heln, sex: 女, score: 89}nfun(**tuple2)n
輸出結果:
name: woodman
----------name: Bobsex : 男----------
name: Alansex : 男class : 2016012----------name: Helnsex : 女score : 89----------
注意:最後一行,我們將參數name也放入了字典tuple2中,通過**tuple2傳入函數,這樣也是可用的。
推薦閱讀:
※Python學習如何下手?看完本文後你能明白60%
※讓彈幕飄一會兒的Python小實驗
※Spider與OpenPyXL的結合
※【視頻】字元串,今天你學習了嗎