函數,遞歸函數,返回值作用域,插入排序
數學定義:y=f(x) ,y是x的函數,x是自變量。y=f(x0, x1, ..., xn)
Python函數
由若幹語句組成的語句塊、函數名稱、參數列表構成,它是組織代碼的最小單元完成一定的功能
函數的作用
結構化編程對代碼的最基本的封裝,一般按照功能組織一段代碼封裝的目的為了復用,減少冗余代碼代碼更加簡潔美觀、可讀易懂
函數的分類
內建函數,如max()、reversed()等庫函數,如math.ceil()等
def語句定義函數
def 函數名(參數列表):
函數體(代碼塊)
[return 返回值]
函數名就是標識符,命名要求一樣語句塊必須縮進,約定4個空格Python的函數沒有return語句,隱式會返回一個None值定義中的參數列表成為形式參數,只是一種符號表達,簡稱形參
函數定義,只是聲明了一個函數,它不會被執行,需要調用調用的方式,就是函數名加上小括號,括號內寫上參數調用時寫的參數是實際參數,是實實在在傳入的值,簡稱實參
參數調用時傳入的參數要和定義的個數相匹配(可變參數例外)
位置參數
def f(x, y, z) 調用使用 f(1, 3, 5)按照參數定義順序傳入實參
關鍵字參數
def f(x, y, z) 調用使用 f(x=1, y=3, z=5),使用形參的名字來出入實參的方式,如果使用了形參名字,那麽傳參順序就可和定義順序不同
傳參
f(z=None, y=10, x=[1])
f((1,), z=6, y=4.1)
f(y=5, z=6, 2) #
要求位置參數必須在關鍵字參數之前傳入,位置參數是按位置對應的
參數默認值(缺省值)
定義時,在形參後跟上一個值
def add(x=4, y=5):
return x+y
測試調用 add(6, 10) 、add(6, y=7) 、add(x=5) 、add()、add(y=7)、 add(x=5, 6) 、add(y=8,
4)、add(x=5, y=6)、add(y=5, x=6)
測試定義後面這樣的函數 def add(x=4,y)
作用
參數的默認值可以在未傳入足夠的實參的時候,對沒有給定的參數賦值為默認值
參數非常多的時候,並不需要用戶每次都輸入所有的參數,簡化函數調用
舉例
定義一個函數login,參數名稱為host、port、username、password
可變參數
位置參數的可變參數
有多個數,需要累加求和
在形參前使用*表示該形參是可變參數,可以接收多個實參
收集多個實參為一個tuple
關鍵字參數的可變參數
形參前使用*符號,表示可以接收多個關
可變參數混合使用
總結
有位置可變參數和關鍵字可變參數
位置可變參數在形參前使用一個星號
關鍵字可變參數在形參前使用兩個星號**
位置可變參數和關鍵字可變參數都可以收集若幹個實參,位置可變參數收集形成一個tuple,關
鍵字可變參數收集形成一個dict
混合使用參數的時候,可變參數要放到參數列表的最後,普通參數需要放到參數列表前面,位
置可變參數需要在關鍵字可變參數之前
keyword-only參數(Python3加入)
如果在一個星號參數後,或者一個位置可變參數後,出現的普通參數,實際上已經不是普通的
參數了,而是keyword-only參數
編寫一個函數,接受一個參數n,n為正整數,左右兩種打印方式。要求數字必須對齊
函數的返回值
Python函數使用return語句返回“返回值”
所有函數都有返回值,如果沒有return語句,隱式調用return None
return 語句並不一定是函數的語句塊的最後一條語句
一個函數可以存在多個return語句,但是只有一條可以被執行。如果沒有一條return語句被執
行到,隱式調用return None
如果有必要,可以顯示調用return None,可以簡寫為return
如果函數執行了return語句,函數就會返回,當前被執行的return語句之後的其它語句就不會
被執行了
作用:結束函數調用、返回值
函數嵌套
函數嵌套
在一個函數中定義了另外一個函數
函數有可見範圍,這就是作用域的概念
內部函數不能在外部直接使用,會拋NameError異常,因為它不可見
作用域***
作用域
一個標識符的可見範圍,這就是標識符的作用域。一般常說的是變量的作用域
全局作用域
在整個程序運行環境中都可見
局部作用域
在函數、類等內部可見
局部變量使用範圍不能超過其所在的局部作用域
從嵌套結構例子看出
外層變量作用域在內層作用域可見
全局變量global,使用global關鍵字的變量
global使用原則
外部作用域變量會內部作用域可見,但也不要在這個內部的局部作用域中直接使用,因為
函數的目的就是為了封裝,盡量與外界隔離
如果函數需要使用外部全局變量,請使用函數的形參傳參解決
自由變量:未在本地作用域中定義的變量。例如定義在內存函數外的外層函數的作用域中的變量
閉包:就是一個概念,出現在嵌套函數中,指的是內層函數引用到了外層函數的自由變量,就形成
了閉包。
使用了nonlocal關鍵字,將變量標記為不在本地作用域定義,而在上級的某一級局部作用域中定義,但不
能是全局作用域中定義
變量名解析原則LEGB
Local,本地作用域、局部作用域的local命名空間。函數調用時創
建,調用結束消亡
Enclosing,Python2.2時引入了嵌套函數,實現了閉包,這個就
是嵌套函數的外部函數的命名空間
Global,全局作用域,即一個模塊的命名空間。模塊被import時
創建,解釋器退出時消亡
Build-in,內置模塊的命名空間,生命周期從python解釋器啟動
時創建到解釋器退出時消亡。例如 print(open),print和open都
是內置的變量
所以一個名詞的查找順序就是LEGB
插入排序
直接插入排序原理
在未排序序列中,構建一個子排序序列,直至全部數據排序完成
將待排序的數,插入到已經排序的序列中合適的位置
增加一個哨兵,放入待比較值,讓它和後面已經排好序的序列比較,找到合適的插入點
匿名函數
匿名,即沒有名字
匿名函數,即沒有名字的函數
沒有名字如何定義
沒有名字如何調用
如果能調用,如何使用
匿名函數
使用lambda關鍵字來定義匿名函數
參數列表不需要小括號
冒號是用來分割參數列表和表達式的
不需要使用return,表達式的值,就是匿名函數返回值
lambda表達式(匿名函數)只能寫在一行上,被稱為單行函數
用途
在高階函數傳參時,使用lambda表達式,往往能簡化代碼
遞歸Recursion
遞歸要求
遞歸一定要有退出條件,遞歸調用一定要執行到這個退出條件。沒有退出條件的遞歸調用,就是無限
調用
遞歸調用的深度不宜過深
Python對遞歸調用的深度做了限制,以保護解釋器
超過遞歸深度限制,拋出RecursionError: maxinum recursion depth exceeded 超出最大深
度
sys.getrecursionlimit()
遞歸的性能
循環稍微復雜一些,但是只要不是死循環,可以多次叠代直至算出結果
fib函數代碼極簡易懂,但是只能獲取到最外層的函數調用,內部遞歸結果都是中間結果。而且給定一個n
都要進行近2n次遞歸,深度越深,效率越低。為了獲取斐波那契數列需要外面在套一個n次的循環,效率
就更低了
遞歸還有深度限制,如果遞歸復雜,函數反復壓棧,棧內存很快就溢出了
遞歸總結
遞歸是一種很自然的表達,符合邏輯思維
遞歸相對運行效率低,每一次調用函數都要開辟棧幀
遞歸有深度限制,如果遞歸層次太深,函數反復壓棧,棧內存很快就溢出了
如果是有限次數的遞歸,可以使用遞歸調用,或者使用循環代替,循環代碼稍微復雜一些,但是只要不是
死循環,可以多次叠代直至算出結果
絕大多數遞歸,都可以使用循環實現
即使遞歸代碼很簡潔,但是能不用則不用遞歸
函數,遞歸函數,返回值作用域,插入排序