1、函數的定義及調用
In [173]: def add(x,y): ...: print(x+y) ...: return x + y ...: In [174]: add(3,5) 8 Out[174]: 8
2、函數的參數
In [177]: def add(x,y): ...: ret = x + y ...: print('{} + {} = {}'.format(x,y,ret)) ...: return ret ...: ...: In [178]: add(3,5) #參數按照定義的順序傳入,這樣的傳參方法叫位置參數 3 + 5 = 8 Out[178]: 8 In [179]: In [179]: add(y=3,x=5) #參數按照定義時的變量名傳遞,這樣的傳參方法叫關鍵字參數 5 + 3 = 8 Out[179]: 8 In [181]: def inc(base,x=1): #x=1就代表是默認值參數 ...: return base + x ...: In [182]: inc(3) Out[182]: 4 In [183]: inc(3,2) Out[183]: 5 可變參數 In [184]: def sum(*lst): ...: print(type(lst)) ...: ret = 0 ...: for x in lst: ...: ret += x ...: return ret ...: #*lst 參數前加一個星號,表示這個參數是可變的,也就是可以接受任意多個參數,這些參數將 構成一個元組,此時只能通過位置參數傳參 In [185]: sum(1,2,3) <class 'tuple'> Out[185]: 6 In [186]: def connect(**kwargs): ...: print(type(kwargs)) ...: for k,v in kwargs.items(): ...: print('{} => {}'.format(k,v)) ...: #**kwargs 參數前面加兩個星號,表示這個參數是可變的,可以接受任意多個參數,這些參數構成 一個字典,此時只能通過關鍵字參數傳參 In [187]: connect(host='127.0.0.1',port=3306) <class 'dict'> port => 3306 host => 127.0.0.1 可變參數兩種形式: 位置可變參數 : 參數名前加一個星號, 構成元組, 傳參只能以位置參數的形式 關鍵字可變參數: 參數名前加兩個信號, 構成字典, 傳參只能以關鍵字參數的形式 In [190]: def fn(x,y,*args,**kwargs): ...: print(x) ...: print(y) ...: print(args) ...: print(kwargs) ...: In [191]: fn(1,2,3,4,5,a=1,b=2) 1 2 (3, 4, 5) {'a': 1, 'b': 2} 通常來說: 默認參數靠後 可變參數靠後 默認參數和可變參數不同時出現
3、參數解構
In [192]: def add(x,y): ...: ret = x + y ...: print('{} + {} = {}'.format(x,y,ret)) ...: return ret ...: In [193]: add(1,2) 1 + 2 = 3 Out[193]: 3 In [194]: t = 1,2 In [195]: t Out[195]: (1, 2) In [196]: add(t[0],t[1]) 1 + 2 = 3 Out[196]: 3 In [197]: In [197]: add(*t) 1 + 2 = 3 Out[197]: 3 #*t 位置參數解構,加一個星號,可以把可迭代對象解構成位置參數 In [198]: add(*range(2)) 0 + 1 = 1 Out[198]: 1 In [199]: In [199]: d = {'x':1,'y':2} In [200]: add(**d) 1 + 2 = 3 Out[200]: 3 #**d 關鍵字參數解構,加兩個星號,可以把字典解構成關鍵字參數 參數解構的兩種形式 一個星號 解構的對象:可迭代對象 解構的結果:位置參數 兩個星號 解構的對象:字典 解構的結果:關鍵字參數 keyword-only參數 In [201]: def fn(*,y): ...: print(y) ...: #* 星號之後的參數只能通過關鍵字參數傳遞,交過keyword-only參數 In [202]: fn(y=3) 3
4、參數的作用域
In [203]: def fn(): ...: x = 1 ...: print(x) ...: def inner(): ...: print(x) ...: inner() ...: In [204]: fn() 1 1 #上級作用域對下級可見
5、匿名函數
In [208]: lambda x: x+1 Out[208]: <function __main__.<lambda>> In [209]: (lambda x: x+1)(3) Out[209]: 4 In [210]: f = lambda x: x+2 In [211]: f(2) Out[211]: 4 lambda 來定義 參數列表不需要用小括號 冒號不是用來開啓新語句塊 沒有return, 最後一個表達式的值即返回值
6、生成器
In [212]: def g(): ...: for x in range(10): ...: yield x #yield表示彈出一個值 ...: In [213]: r = g() #函數已經執行完成,函數的現場應該已經被銷燬,但是事實上,函數的現場 並沒有被銷燬 In [214]: r Out[214]: <generator object g at 0x7f3d60330938> In [215]: next(r) Out[215]: 0 In [216]: next(r) Out[216]: 1 In [217]: next(r) Out[217]: 2 In [218]: def gen(): ...: print('a') ...: yield 1 ...: print('b') ...: yield 2 ...: return 3 ...: In [219]: g = gen() #執行生成器函數的時候,函數體並沒有被執行 In [220]: next(g) #執行到第一個yield,停止執行 a Out[220]: 1 In [221]: next(g) #從第一個yield之後開始執行, 在第二個yield的時候停止 b Out[221]: 2 帶yield語句的函數稱之爲生成器函數, 生成器函數的返回值是生成器 生成器函數執行的時候,不會執行函數體 當next生成器的時候, 當前代碼執行到之後的第一個yield,會彈出值,並且暫停函數 當再次next生成器的時候,從上次暫停處開始往下執行 當沒有多餘的yield的時候,會拋出StopIteration異常,異常的value是函數的返回值 In [226]: def counter(): ...: x = 0 ...: while True: ...: x += 1 ...: yield x ...: In [227]: def inc(c): ...: return next(c) ...: In [228]: c = counter() In [229]: inc(c) Out[229]: 1 In [230]: inc(c) Out[230]: 2 In [231]: d = counter() In [232]: next(d) Out[232]: 1 In [233]: next(d) Out[233]: 2 In [234]: next(d) Out[234]: 3 In [242]: def make_inc(): ...: def counter(): ...: x = 0 ...: while True: ...: x += 1 ...: yield x ...: c = counter() ...: return lambda: next(c) ...: ...: ...: In [243]: incr = make_inc() In [244]: incr Out[244]: <function __main__.make_inc.<locals>.<lambda>> In [245]: incr() Out[245]: 1 In [246]: incr() Out[246]: 2