# ************** 函數 ******************** #位置參數、可變參數、關鍵字參數、命名關鍵字參數、 關鍵字參數 # 1.位置參數、計算x^2的函數x 就是位置參數 def power(x): return x*x print("兩個數的平方和:",power(20)) # 2.默認參數 b=2 就是默認參數 def power(a,b=2): s = 1 while b > 0: s = s * a b = b - 1 return s print("5的2次方:",power(5,2)) # ==> 5的2次方: 25 print("6的2次方:",power(2)) # ==> 6的2次方: 4 print("6的3次方:",power(6,3)) # ==> 6的3次方: 216 print("6的1次方:",power(6,1)) # ==> 6的3次方: 6 # 3.可變參數:可變參數就是傳入的參數個數是可變的,能夠是1個、2個到任意個,還能夠是0個 爲了使參數是可變的須要參數前加* 如calc(numbers) calc(1,2,3) 這麼寫就須要加* def calc(numbers): sum = 0 for x in numbers: sum += x return sum print("1~100的和:",calc(range(101))) # ==> 1~100的和: 5050 print("1~10的和:",calc([1,2,3,4,5,6,7,8,9,10])) # ==> 1~10的和: 55 def test(L = []): L.append("End") return L print(test()) # ==> ['End'] print(test()) # ==> ['End', 'End'] print(test([1,2,3])) # ==> [1, 2, 3, 'End'] print(test()) # ==> ['End', 'End', 'End'] # 備註:當調用test函數的時候若是傳入爲空咱們能夠發現結果就會發生變化,緣由是test函數定義的時候指向了一個空的list,若是傳入不爲空的list那麼L會指向傳入的list而後執行test的函數內容最後返回,此時若是傳入爲空那麼L仍然指向空的list此時執行test函數拼接"End",此時L的默認參數就再也不爲空了,而是有一個元素爲"End"的list,一次類推,因此默認參數必定要選擇不可變對象 # 4.直接把list或者tuple當作參數寫入很不方便,咱們能夠以*list/tuple當作參數寫入同時定義函數的地方的參數也要進行修改,def cals(*numbers) def calcc(*numbers): sum = 0 for x in numbers: sum += x return sum numberss = [1,2,4] print("輸出*list/tuple爲參數的結果:",calcc(*numberss))# *numberss表示把nums這個list的全部元素做爲可變參數傳進去 # ==> 輸出*list/tuple爲參數的結果: 7 # 5.關鍵字參數 可變參數容許你傳入0個或任意個參數,這些可變參數在函數調用時自動組裝爲一個tuple。而關鍵字參數容許你傳入0個或任意個含參數名的參數,這些關鍵字參數在函數內部自動組裝爲一個dict。eg: def person(name, age, **kw): print('name:', name, 'age:', age, 'other:', kw) person(23,34) # ==> name: 23 age: 34 other: {} person("gfengwei",20,agee=20) # ==> name: gfengwei age: 20 other: {'agee': 20} # 5.1 擴展函數使用 extra = {'city': 'Beijing', 'job': 'Engineer'} person('Jack', 24, **extra) #備註:**extra表示把extra這個dict的全部key-value用關鍵字參數傳入到函數的**kw參數,kw將得到一個dict,注意kw得到的dict是extra的一份拷貝,對kw的改動不會影響到函數外的extra。 ==> name: Jack age: 24 other: {'job': 'Engineer', 'city': 'Beijing'} # 6. 命名關鍵字 和關鍵字參數**kw不一樣,命名關鍵字參數須要一個特殊分隔符*,*後面的參數被視爲命名關鍵字參數。若是函數定義中已經有了一個可變參數,後面跟着的命名關鍵字參數就再也不須要一個特殊分隔符*了: # 6.1 關鍵字,在函數的調用者能夠傳入任意不受限制的關鍵字參數,例如上面的city,job咱們能夠任意傳,至於到底傳入了哪些,咱們能夠在函數的內部經過kw進行檢查. # 以person()函數爲例,咱們但願檢查是否有city和job參數: def person(name,age,**kw): if "city" in kw: print("有city參數而後作出處理") pass if "job" in kw: print("有job參數而後作出處理") pass print("name:",name,"age:",age,'other:',kw) person("fenwei",24,**extra) # ==> 有city參數而後作出處理 有job參數而後作出處理 name: fenwei age: 24 other: {'job': 'Engineer', 'city': 'Beijing'} # 6.2備註:命名關鍵字參數必須傳入參數名 # 7.位置參數 默認參數 可變參數 命名關鍵字參數**kw 就是一個擴展dict、命名關鍵字參數 # 順序:必選參數、默認參數、命名關鍵字參數、關鍵字參數 def person(name,age,sex="男",*args,**kw): print("name:",name,"age:",age,"sex:",sex,"args:",args,"kw:",kw) person("gz",24) # ==> name: gz age: 24 sex: 男 args: () kw: {} person("gz",24,"男","nongmin","nomoney") # ==> name: gz age: 24 sex: 男 args: ('nongmin', 'nomoney') kw: {} person("gz",24,"男","nongmin","nomoney",city="hangzhou",country="china") # ==> name: gz age: 24 sex: 男 args: ('nongmin', 'nomoney') kw: {'country': 'china', 'city': 'hangzhou'} args = (1,2,3,4) kw = {"a":"123","b":"456"} person(*args,**kw) # 8.遞歸函數 遞歸函數須要注意防止棧溢出,遞歸調用的次數過多,會致使棧溢出 def func(n): if n == 1: return n return n * func(n-1) print("遞歸100階乘:",func(100)) # 1000階乘致使棧溢出 # 8.1解決棧溢出:尾遞歸優化 # 9.漢諾塔 def hanoi(n,x,y,z): if n==1: print(x,'-->',z) else: hanoi(n-1,x,z,y)#將前n-1個盤子從x移動到y上 hanoi(1,x,y,z)#將最底下的最後一個盤子從x移動到z上 hanoi(n-1,y,x,z)#將y上的n-1個盤子移動到z上 n=int(input('請輸入漢諾塔的層數:')) hanoi(n,'x','y','z')