函數是組織好的,可重復使用的,用來實現單一,或相關功能的代碼段。
函數能提高應用的模塊性,和代碼的重復使用率。
?
定義一個函數
可以定義一個由自己想要功能的函數,以下是簡單規則:
- l? 函數代碼塊是以def關鍵詞開頭,后接函數標識符名稱和圓括號。
- l? 任何傳入參數和自變量都必須放在圓括號中,圓括號之間可以用來定義參數。
- l? 函數的第一行語句可以選擇性的使用文檔字符串—用于存放函數說明。
- l? 函數內容以冒號起始,并且縮進。
- l? return[表達式]結束函數,選擇性的返回一個值給調用方。不帶表達式的return相當于None
?
語法:
Python定義函數使用def關鍵字,一般格式如下:
def 函數名(參數列表)函數體
默認情況下,參數值和參數名稱是按函數聲明中的定義順序匹配的。
?
參數傳遞
在python中,類型屬于對象,對象是沒有類型的。
a = [1,2,3]
a = “Runoob”
以上代碼中,[1,2,3]是List類型,“Runoob”是String類型,而變量a是沒有類型的,她僅僅是一個對象的引用(一個指針),可以是指向List類型的對象,也可以是指向String類型對象。
可更改和不可更改對象
在Python中,string,tuples和numbers是不可更改的對象,而list,dict等則是可以修改的對象。
不可變類型:變量賦值后a=5后再賦值a=10,這里實際是生成一個int對象10,再讓a指向它,而5被拋棄,而不是改變了a的值,相當于重新生成了a。
可變類型:變量賦值la = [1,2,3,4]后再賦值la[2] = 5則是將list la的第三個元素更改,本身la沒有動,只是其內部的一部分值被修改了。
?
python函數的參數傳遞:
不可變類型:類似于C++的值傳遞,如整數,字符串,元組。
可變類型:類似于C++引用傳遞,如列表,字典。
?
python中一切都是對象,嚴格意義上我們不能說值傳遞還是引用傳遞,我們應該說,傳不可變對象和傳可變對象。
?
python傳不可變對象實例:
#immutable.py def ChangeInt(a):a = 10b = 2 ChangeInt(b) print(b)
運行結果:
robot@ubuntu:~/wangqinghe/python/20190828$ python3 immutable.py
2
實例中由int對象2,指向它的變量是b,在傳遞給ChangeInt函數時,按傳值的方式復制了變量b,a和b都指向了同一個int對象,在a=10時,則新生成了一個int對象10,并讓a指向了它。
?
傳可變對象實例:
可變對象在函數里修改了參數,那么在調用這個函數的函數里,原始的參數也被改變了。
#mutable.py def changeme(mylist):mylist.append([1,2,3,4])print("In funciton :",mylist)return mylist = [100,200,300] changeme(mylist) print("outside function : ",mylist)
運行結果:
robot@ubuntu:~/wangqinghe/python/20190828$ python3 mutable.py
In funciton : [100, 200, 300, [1, 2, 3, 4]]
outside function :? [100, 200, 300, [1, 2, 3, 4]]
?
傳入函數的和在末尾添加新內容的對象用的是同一個引用
?
參數
以下是調用函數時可使用的正式參數類型:
- l? 必需函數
- l? 關鍵字函數
- l? 默認函數
- l? 不定長函數
?
必需參數
必需參數須以正確的順序傳入函數。調用時數量必須和聲明時的一樣。
?
關鍵字參數
關鍵字參數和函數調用關系緊密,函數調用使用關鍵字參數來確定傳入的參數值。
使用關鍵字允許函數調用時參數順序與聲明時不一致,因為Python解釋器能夠使用參數名稱匹配參數值。
##函數參數使用不需要使用指定順序:def printinfo(name,age):print("name : ",name)print("age : ",age)return printinfo(age = 20,name = "jack")運行結果: robot@ubuntu:~/wangqinghe/python/20190828$ python3 seq.py name : jack age : 20
默認參數:
調用函數時,如果沒有傳遞參數,則會使用默認參數
#default.py def printinfo(name,age = 35):print("name :",name)print("age : ",age)return printinfo(age = 20,name = "wangqinghe") print("-----------------") printinfo(name = "wangqinge")
運行結果:
robot@ubuntu:~/wangqinghe/python/20190828$ python3 default.py
name : wangqinghe
age :? 20
-----------------
name : wangqinge
age :? 35
?
不定長參數
你可能需要一個函數能處理比當初聲明時更多的參數,這些參數叫做不定長參數,和上述兩種參數不同,聲明時不會命名。
語法如下:
def functionname([formal_args,],*var_args_tuple):function_suitereturn [expresssion]
加*號的參數會以元組的形式導入,存放所有未命名的變量參數。
#random_length.py def printinfo(arg1,*vartuple):print("output : ")print(arg1)print(vartuple)printinfo(70,60,50)
運行結果:
robot@ubuntu:~/wangqinghe/python/20190828$ python random_length.py
output :
70
(60, 50)
如果在函數調用時沒有指定參數,它就是一個空元組,我們也可以不想函數傳遞未命名的變量:
#unnaming.py def printinfo(arg1,*vartuple):print("output : ")print(arg1)for var in vartuple:print(var)return printinfo(10) printinfo(70,60,50)
運行結果:
robot@ubuntu:~/wangqinghe/python/20190828$ python3 unnaming.py
output :
10
output :
70
60
50
?
還有一種是參數帶有兩個**,基本語法如下:
def functionname([formal_args,] **var_args_dict):function_suitereturn [expression]
加了兩個星號,參數會以字典的形式導入
#dic_param.py def printinfo(arg1,**vardict):print("output")print(arg1)print(vardict)printinfo(1,a=2,b=3)
運行結果:
robot@ubuntu:~/wangqinghe/python/20190828$ python3 dic_param.py
output
1
{'a': 2, 'b': 3}
?
聲明函數時,參數中信號*可以單獨出現,
def f(a,b,*,c)
?????? return a+b+c
?
如果單獨出現星號后的參數,必須以關鍵字傳入
?
?
匿名函數
python使用lambda來創建匿名函數。
所謂匿名,就是不再使用def語句這樣標準的形式定義一個函數。
lambda只是一個表達式,函數體比def簡單的多
lambda的主體是一個表達式,而不是一個代碼塊,僅僅能在lambda表達式中封裝有限的邏輯進去。
lambda函數擁有自己的命名空間,且不能訪問自己參數列表之外或全局命名空間里的參數。
雖然lambda函數看起來只能寫一行,卻不等同于C/C++的內聯函數,后者的目的調用小函數時不占用棧空間從而增加運行效率。
?
語法:
lambda函數的語法只包含一個語句。
lambda[arg1[,arg2,…argn]]:expression
#lambda.py sum = lambda arg1,arg2:arg1+arg2print("a + b : ",sum(10,20)) print("a + b : ",sum(20,20))
運行結果:
robot@ubuntu:~/wangqinghe/python/20190828$ python3 lambda.py
a + b :? 30
a + b :? 40
?
return語句:
return[表達式]語句用于退出函數,選擇性地向調用方返回一個表達式,不帶參數值地return語句返回None。
#return.py def sum(arg1,arg2):total = arg1 + arg2print("Inside fun : ",total)return totaltotal = sum(10,20) print("Outside fun : ",total)
運行結果:
robot@ubuntu:~/wangqinghe/python/20190828$ python3 return.py
Inside fun :? 30
Outside fun :? 30
?
變量作用域
Python中,程序變量并不是在哪個位置都可以訪問地,訪問權限決定于這個變量在哪里賦值地。
變量地作用域決定了在哪一部分可以訪問哪個特定地變量名稱。python地作用域一共4種,分別是:
- L(local):局部作用域
- E(E你closing):閉包函數外的函數體中
- G(Global)全局作用域
- B(Built-in)內置作用域(內置函數所在模塊地范圍)
以L->E->G->B地規則去找,即:在局部找不到,就去局部外去找,再找不到就去全局找,再去內置找。
g_count = 0 #全局作用域 def outer():o_count = 1 #閉包函數外的函數中def inner(0:i_count = 2 #局部作用域
內置作用域時通過一個叫built地標準模塊實現的,但是這個變量名自身并沒有放入內置作用域中,所有必須導入這個文件才能使用,在python3中,可以是以下的代碼查看到底預定義了哪些變量。
inport builtins
dir(builtins)
Python中只有模塊(module),類(class)以及函數(def、lambda)才會引入新的作用域,其他代碼塊(if/elif/else、try/exception、for/while等)是不會引入新的作用域的,也就是說這些語句內定義的變量,外部亦可以訪問
?
全局變量和局部變量
定義在函數內部的變量擁有一個局部作用域,定義在函數外的擁有全局作用域。
局部變量只能在其被聲明的函數內部訪問,而全局變量可以在整個程序范圍內訪問,調用函數時,所有在函數內聲明的變量名稱都將被加入到作用域中
?