Python第四課----函數
阿新 • • 發佈:2017-10-13
python
函數
一、函數
由若幹語句組成的語句塊,函數名稱、參數列表構成,它是組織代碼的最小單元。
二、函數的作用
1、對代碼的最基本封裝,按照功能組織一段代碼。 2、目的為了復用,減少冗余代碼。
三、函數分類
1、內建函數:max(),reversed()。 2、庫函數:math.ceil。
四、def語句定義函數
def 函數名(參數列表) 函數體(代碼塊) [return 返回值] 函數名就是標識符,命名要求一樣。 語句塊縮進四個空格。 函數中如果沒有return語句,隱式會返回一個None值。 定義中的參數列表是形式參數,只是一種表達,簡稱形參。
2、調用 函數定義,只是聲明,不會執行,需要調用 加上小括號調用 調用時寫的參數是實際參數,是傳入的值,簡稱實參
五、函數的定義,調用
def add(x,y): result = x+y return result out = add(4,5) print(out)
函數---->add,計算結果通過返回值返回、返回值可以使用變量接收,函數是可調用對象,callable(add)試一下,是通用的
六、函數參數
1、參數調用時,傳入的參數要和定義的個數匹配(可變例外) 2、位置參數:def f(x,y,z) 調用時:f(3,4,5),按照順序傳入實參 3、關鍵參數:def f(x,y,z) 調用時:f(x=3,y=4,z=5),使用形參名字傳入實參的方式,順序無所謂 4、傳參:f(z=None,y=10,x=[1])、f((1,),z=6,x=4.1)、f(y=5,z=6,2)最後這種不行,位置參數必須在關鍵字參數之前傳入
七、參數默認值
1、參數默認值:def f(x=4,y=5):這個時候,x,y都有默認值,默認可以輸出 2、參數非常多的時候,並不需要輸出所有參數,有默認值就可以了
八、可變參數
1、問題:有多個數,累加求和 def add(nums):----這樣的話,nums需要是一個可叠代對象 2、可變位置參數(一個星號)一個形參可以匹配任意個參數x def add(*args):----sum=0,for x in args:----sum+=x 3、可變關鍵字參數(兩個星號) def add(**kwargs): for k,v in kwargs.items( ): print(“{}={}”.format(k,v)) add(x=1,y=2) 只能用關鍵字調用,組成的是個字典 4、混合使用參數、可變參數: 1、def showconfig(username,password,**kwargs) 2、def showconfig(username,*args,**kwargs) 3、def showconfig(username,password=“mage”,*args,**kwargs) 4、def fn(*args,x,y,**kwargs):---->這麽寫,調用必須對唯一關鍵詞x、y進行關鍵字傳參 5、fn(*,x,y)強制將x,y變成唯一關鍵詞 6、fn(*agrs,x=5)默認值給了可以直接調用fn()
九:參數解構----實參解構
1、fn(x,y): return(x+y) fn(*(4,5))/*[4,5]/*{4,5}/fn(*range(1,3))/fn((1,2)[0],[3][0]) 2、字典解構fn(**{x:5,y:6})或者fn(*d.keys())或d.valus() 3、def fn(*args): print(args) fn(*[1,2,3]) 4、def fn(*args): sum = 0 for x in args: sum += x print(sum)
十:返回值
十一:作用域
1、一個標識符的可見範圍,也就是變量,一般說變量的作用域
2、x = 5 x = 5 def foo(): def foo(): print(x) x+=1 foo() print(x) 可執行,x為全局變量 foo()不可執行,下方的x+=1,實際上是重新定義變量x,但是並不存在
3、全局作用域,global變量,可以管轄下面的函數,但函數內部高度自治,自己管自己局部作用域,local變量,裏面可以使用外部的變量,但本地變量,只能在內部使用,外部不可見
4、嵌套結構 def outer( ): def outer( ): o = 65 o = 65 def inner( ): def inner( ): print("inner { }".format(o)) o = 97 print(chr(o)) print("inner { }".format(o)) print("outer { }".format(o)) print(chr(o)) inner( ) print("outer { }".format(o)) outer( ) 打印65,65,A inner( ) 外部變量內部可用,但賦值即定義 outer( )打印結果65,97,a
x = 5 def foo( ): y = x+1 x = 1 print(x) foo( )報錯,賦值即定義,上面x用不上,下面的又沒有定義就被y拿來使用
5、全局變量global x = 5 def foo(): def foo(): global x global x x = 10 x+=1 x +=1 將x聲明為使用外部的全局作用域,外面必須有x的定義 這個x=10,是全局變量,是為外面定義一個變量
6、閉包 自由變量:未在本地作用域定義的變量,例如定義在外層函數作用域的變量 閉包:出現在嵌套函數中,指的是內層函數引用了外層函數的自由變量 def counter(): c = [0] def inc( ): c[0] += 1 return c[0] return inc foo = counter( ) print(foo( ),foo( )) c = 100 print(foo( )) 每次局部變量應該消失,但[ ]是引用對象,每次都會改變,借用的是引用類型
7、nonlocal關鍵字----關鍵字絕對不能被占用 使用了nonlocal關鍵字,將變量標記為在上級的局部作用域中定義,是上級的局部作用域,而不是全局作用域 函數調用為什麽會循環count+=1??? def counter(): count = 0 def inc(): nonlocal count count +=1 return count return inc foo = counter( ) print(foo( ),foo( )) 閉包內的函數,在外面foo調用的時候,保留了count這個變量,而且每次都執行了+1
8、函數默認值的作用域:(foo.__defaults__)使用兩個下劃線+defaults+兩個下劃線 def foo(xyz=[]): xyz.append(1) print(xyz) print(foo(),id(foo)) print(foo.__defaults__) print(foo(),id(foo)) print(foo.__defaults__) 函數的默認值不會發生變化,缺省值不會改變,是個元組,但元組內的列表發生了改變,這是個引用
def foo(w,u="abc",z=123): u = "xyz" z = 456 print(w,u,z) print(foo.__defaults__) foo("magedu") print(foo.__defaults__) 函數的默認值不會發生改變,重新賦值的展示在函數調用裏
9、默認值的作用域用法: def foo(xyz=[],u="abc",z=123): xyz=xyz[:] xyz.append(1) print(xyz) foo() print(foo.__defaults__) foo() print(foo.__defaults__) foo([10]) print(foo.__defaults__) foo([10,5]) print(foo.__defaults__) xyz重新被賦值定義,做了拷貝,原xyz還是不變,默認值始終不變
def foo(xyz=None,u="abc",z=123): if xyz is None: xyz=[] xyz.append(1) print(xyz) foo() print(foo.__defaults__) foo() print(foo.__defaults__) lst = [10] foo(lst) print(lst) print(foo.__defaults__) foo([10,5]) print(foo.__defaults__) 使用不可變類型默認值,如果使用none,則創建新列表,如果,傳入一個列表,就修改這個列表,lst發生了變化,但是默認值一直沒有發生變化,始終是None,abc,123的元組
def foo(x=None): if x == None: x = [] x.append(1) return x lst = foo() a = foo(lst) print(a) 一般這麽寫函數,lst=foo()就會執行一次foo(),結果是[1],a=foo(lst)會再執行一次,結果就是[1,1]
十二、函數銷毀:
del或重新賦值
十三、樹:
1、定義: (1)、非線性解構,每個元素可以有多個前驅和後繼(這句話,是前驅0或1,後繼多個) (2)、樹是n≥0個元素的集合 (3)、n = 0,則是空樹,樹的根Root沒有前驅 (4)、其余元素只能有一個前驅,多個後繼 2、遞歸定義: (1)、有且只有一個特殊元素根,其余元素劃分為m個互不相交的集合T1,T2.。。。Tm,每一個集合都是樹,稱為T的子樹Subtree (2)、子樹也有自己的根 3、樹的概念 (1)、結點,樹中的數據元素,每個元素都是一個結點 (2)、結點的度degree:結點擁有的子樹的數目,稱為度,記作d(v),B的度是1,C的度是2,D的度是3 (3)、葉子結點,結點的度為0,則是葉子結點leaf、終端結點,末端結點 (4)、分支結點,結點度不為0,則是分支結點 ABCDE (5)、分支,結點之間的關系,A和B的分支,關系,這條線 (6)、內部結點,除掉根和葉子結點,中間的結點 (7)、樹的度:樹內各結點,誰的度數大,樹的度數就是多少,上圖為3 (8)、孩子(兒子Child)結點,結點的子樹的根節點成為成為該結點的孩子 (9)、雙親(父Parent)結點:一個結點是它各個子樹的根結點的雙親 (10)、兄弟結點(sibling):具有相同雙親結點的結點 (11)、祖先結點:從根結點到該結點所經分支上所有的結點。ABD都是G的祖先 (12)、子孫結點:結點的所有子樹上的結點都成為該結點的子孫,B的子孫是GDHI (13)、結點的層次(Level):根結點為第一層,根的孩子是第二層,以此類推,記作L(v) (14)、樹的深度(高度Depth):樹的層次的最大值,上圖深度為4 (15)、堂兄弟,雙親在同一層的結點 4、樹的概念: (1)、有序樹:結點的子樹是有順序的,不能交換 (2)、無序樹:結點的子樹是無序的,可以交換 (3)、路徑:樹的k個結點n1,n2,。。。nk,滿足ni是n(i+1)的雙親,成為n1到nk的一條路徑,就是一條線下來的,前一個是後一個的父結點,A-B-D-G (4)、路徑長度:路徑上結點數-1 (5)、森林:m≥0顆不相交的樹的集合 D、E、F,結點的子樹集合就是森林 5、樹的特點: (1)、唯一的根 (2)、子樹不相交 (3)、除了根之外,每個元素只有一個前驅,0或多個後繼 (4)、根結點沒有前驅,葉子結點沒有後繼 (5)、如果vi是vj的雙親,則L(vi)=L(vj)-1,雙親比孩子Level小1 (6)、堂兄弟的雙親不一定是兄弟
十四:二叉樹
1、每個結點最多兩顆子樹:二叉樹不存在度數大於二的結點 2、二叉樹是有序樹,左子樹,右子樹是有順序的,不能交換 3、即使某個結點只有一棵樹,也要確定它是左子樹還是右子樹 4、二叉樹的五種形態 (1)、空二叉樹 (2)、只有根結點的二叉樹 (3)、根結點只有左子樹 (4)、根結點只有右子樹 (5)、根結點有左子樹和右子樹
十五、斜樹:
1、左斜樹:全是左子樹 2、右斜樹:全是右子樹
十六、滿二叉樹:
1、一顆二叉樹的所有分支結點都存在左子樹和右子樹,並且葉子結點只存在最下面一層,一個都不能少,左右完全對稱 2、同樣深度中,滿二叉樹結點最多 3、k為深度(1≤k≤n),則結點總數為2**k-1
十七:完全二叉樹:
1、若二叉樹的深度為k,則二叉樹的層數從1到k-1層的結點數都達到了最大個數,在第k曾的所有結點都集中在最左邊,這就是完全二叉樹(最後一層,從左到右,不能空) 2、滿二叉樹一定是完全二叉樹,完全二叉樹不一定是滿二叉樹 3、H在左邊,若E有一個分支結點,則不是,必須D有兩個,E有一個左子樹,才是完全二叉樹
十八、二叉樹性質:
1、在二叉樹的第i層上最多有2**(i-1)個結點 2、深度為k的二叉樹,至多有2**k-1個結點 3、對於任意一顆二叉樹T,如果其終端結點為n0,度數為2的結點為n2,則有n0=n2+1(葉子結點,是度數為2的結點加1)上圖中,葉子結點n0=4(HEFG),n2=3(ABC) 4、葉子結點數-1就等於度數為2的結點數 證明:n0+n1+n2=n(0葉子,1度數為1,2度數為2): n0+n1+n2-1(一棵樹的分支數為n-1(總數減去根結點)) 分支數還等於n0*0+n1*1+n2*2-----2n*2+n1 2*n2+n1=n0+n1+n2-1---->n2=n0-1 5、高度為k的二叉樹,至少有k個結點(左斜樹) 7、具有n個結點的完全二叉樹的深度為int((log2n+1))n開方+1取整,或者math.ceil(log2(n+1)) 8、如果有一顆n個結點的完全二叉樹,可以按照層序編號 (1)、如果i=1,則結點i是二叉樹的根,無雙親,如果i>1,則其雙親是int(i/2),向下取整。就是子結點的編號整除2得到的就是父結點的編號。父節點如果是i,左孩子結點就是2i,右孩子就是2i+1 (2)、如果2i>n,則結點無左孩子,即結點i為葉子結點,否則其左孩子結點存在編號為2i (3)、如果2i+1>n,則結點i無右孩子,否則右孩子存在編號為2i+1
十九、變量名解析原則LEGB
1、Local----先本地作用域,調用結束消亡 2、Enclosing,嵌套函數的閉包的外部函數的命名空間 3、Global----全局,解釋器退出時消亡 4、Build-in 內置模塊的命名空間,解釋器啟動到退出,就是生命周期,print、open等
二十、函數執行流程:
1、函數執行流程: 全局幀中生成foo1、2、3、main函數對象 def foo1(b,b1=3): main函數調用 print("foo1 called",b,b1) main中查找內建函數print壓棧,將常量字符串壓棧,調用函數,彈出棧頂 def foo2(c): main中全局查找函數foo1壓棧,將常量100,101壓棧,調用foo1函數, foo3(c) 創建棧幀,print壓棧,字符串和常量壓棧,調用函數,彈出棧頂,返回值。 print("foo3 called",c) 後續全部類似 def foo3(d): print("foo3 called",d) def main(): print("main called") foo1(100,101) foo2(200) print("main called") main()
二十一、遞歸Recursion
1、函數直接或間接調用自身,就是遞歸
2、遞歸需要邊界條件
3、當不滿足邊界條件時,遞歸前進,當滿足邊界條件時,遞歸結束。
本文出自 “13277682” 博客,謝絕轉載!
Python第四課----函數