Python的函數參數和遞歸參數
位置參數
def power(x):
return x*x;
默認參數
指的是在函數定義的時候,就賦予一些參數默認值,在調用這個函數的時候不必多次傳入重復的參數值。
如定義一個多次輸出同一個年齡階段和同一個城市的學生的姓名和性別。
def info(name,gender,age=20,city=‘sichuan‘): print(‘name:‘, name) print(‘gender:‘, gender) print(‘age‘,age) print(‘city‘,city) info("xiaoqian","nv") info("xiangj",‘nan‘)
從上面可以看出,默認參數可以簡化函數的調用,設置默認參數時,有幾點要註意:
一是必選參數在前,默認參數在後。
二是如何設置默認參數。
但是默認參數雖然好,但是也有坑:就是在定義默認參數的時候,默認參數必須是不可變對象。
可變參數(*)
可變參數就是傳入的參數個數是可變的,可以是1個,2個或多個,甚至是0個
def calc(*numbers):
sum = 0;
for n in numbers:
sum = sum + n;
return sum;
calc();
calc(1,2,3);
如果有一個list或者是tuple,要調用一個可變參數怎麽辦?
python允許在list或者tuple前面加上*,傳給函數。
num = [1,2,3];
cal(*num);
可變參數允許傳入0,1,n個參數,在調用的時候會自動將這些參數組裝成一個tuple。而關鍵字參數允許你傳入0個或人一個含參數名的參數,這些關鍵字參數在函數內部自動組裝成一個dict。
關鍵字參數(**)
def person(name,age,**kw):
print(‘name‘,name,‘age‘,age,‘other‘,kw)
person(‘tom‘,20);
person(‘tom1‘,10,city="beijinh");
person(‘tom2‘,30,gender="m",city="beijing");
也可以將上面的gender和city參數組裝成一個dict後,再傳給函數
extra = {‘city‘:‘beijing‘,‘job‘:‘engin‘};
person(‘tom11‘,100,city=extra[‘city‘],job=extra[‘job‘]);
person("tom11",100,**extra);
//註意這裏kw獲得的是extra的一份拷貝,對kw的改動不會影響到函數外的extra
命名關鍵字參數(*特殊分隔符)
關鍵字參數的調用,函數可以接受不受限制的關鍵字參數。
但是有時候也需要限制關鍵字參數個數,所以這時候就需要用到命名關鍵字參數
def person(name,age,*,city,job):
print(name,age,city,job);
//命名關鍵字參數需要一個特殊分隔符*,*後面的參數被視為命名關鍵字參數。
person("jackl",14,city="beijing",job="gee");
//命名關鍵字參數必須傳入參數名,這和位置參數不同,如果沒有傳入參數名,調用就將報錯
如果函數定義中已經有了一個可變參數,後面跟著的命名關鍵字參數就不需要*這個特殊分隔符了。
def person(name,age,*args,city,job):
print(name,age,args,city,job)
要特別註意:如果沒有可變參數,必須加一個作為特殊分隔符,否則Python將無法識別位置參數和命名關鍵字參數。
總結:
python函數一共有5種參數:必選參數,默認參數,可變參數,關鍵字參數,命名關鍵字參數。可以將這幾個參數組合使用。但是要註意:參數定義的順序必須是:
必選參數,默認參數,可變參數,命名關鍵字參數和關鍵字參數。
默認參數一定要用不可變對象
args是可變參數,args接受的是一個tuple。
kw是關鍵字參數,kw接受的是一個dict。
可變參數可以直接傳入:func(1,2,3),又可以組裝list或者tuple,再通過args傳入:func((1,2,3))
關鍵字參數既可以直接傳入func(a=1,b=2),又可以先組裝dict,然後通過kw傳入func(**{‘a‘:1,‘b‘:2})
命名關鍵字參數是為了限制調用者可以傳入的參數名,同時可以提供默認值。
定義命名的關鍵字出納號蘇時,在沒有可變參數的情況下,不要忘了寫特殊分隔符*,否則定義的將是位置參數。
遞歸函數
遞歸函數的優點是定義簡單,邏輯清晰。但是有時候會出現棧溢出。
解決棧溢出的方法是尾遞歸。事實上,尾遞歸和循環的效果是一樣的,把循環看成一種特殊的尾遞歸函數也是可以的
尾遞歸:在函數返回的時候,調用自身本身,並且,return語句不能包含表達式。
def fact(n):
if n == 1:
return 1
return n * fact(n-1)
上面的return中包含了表達式,這種不是尾遞歸。
def fact_item(num,product):
if num == 1:
return product
return fact_item(num-1,num*product)
上面這種是尾遞歸,做了優化,棧不會增長,因此多少次調用也不會導致棧溢出。
遺憾的是,大多數編程語言沒有針對尾遞歸做優化,Python解釋器也沒有做優化,所以,即使把上面的fact(n)函數改成尾遞歸方式,也會導致棧溢出
Python的函數參數和遞歸參數