函式介紹、函式引數
一、函式的介紹
1、函式是什麼
想象生活中的例子,修理工需要實現準備好工具箱裡面放好錘子,扳手,鉗子等工具,然後遇到錘釘子的場景,拿來錘子用就可以,而無需臨時再製造一把錘子。
修理工=>程式設計師
具備某一功能的工具=>函式
要想使用工具,需要事先準備好,然後拿來就用且可以重複使用
要想用函式,需要先定義,再使用
ps:函式就是盛放程式碼的容器
2、為何要用函式
為了解決下述問題:
1)程式碼的組織結構不清晰,可讀性差
2)遇到重複的功能只能重複編寫實現程式碼,程式碼冗餘
3)功能需要擴充套件時,需要找出所有實現該功能的地方修改之,無法統一管理且維護難度極大
3、如何用函式
3.1、定義的語法
#語法
def 函式名(引數1,引數2,引數3,...):
'''註釋'''
函式體
return 返回的值
呼叫的語法
#函式名要能反映其意義
3.2、定義函式
發生的事情
1)申請記憶體空間把函式體程式碼放進去
2)將函式記憶體地址繫結給函式名
強調:定義函式只檢測語法,不執行程式碼。也就說,語法錯誤在函式定義階段就會檢測出來,而程式碼的邏輯錯誤只有在執行時才會知道
3.3、函式的呼叫
發生的事情:
1)先通過函式名定位到函式的記憶體地址
2)函式記憶體地址()->觸發函式體程式碼的執行
強調:呼叫函式才會執行函式體程式碼
例1: def func(): print(11111 #False 語法錯誤 例2: def func(): print(1111) x print(2222) func() # False 邏輯錯誤 例3 def bar(): print('from bar') def foo(): print('from foo') bar() foo() ================= def foo(): print('from foo') bar() def bar(): print('from bar') foo() #Fales 反了,要先定義,再呼叫
3.4、定義函式的三種形式
- 無參:應用場景僅僅只是執行一些操作,比如與使用者互動,列印
ef say():
print('========')
print('welcome to here')
print('========')
say()
def login(): inp_name = input("username>>>: ").strip() inp_pwd = input("password>>>: ").strip() if inp_name == "egon" and inp_pwd == "123": print('login successful') else: print("username or password error") login()
- 有參:需要根據外部傳進來的引數,才能執行相應的邏輯,比如統計長度,求最大值最小值
def max2(x,y)
if x > y:
print(x)
else:
print(y)
max2(10,20)
- 空函式:設計程式碼結構
def login():
pass
- 結論:
-
定義時無參,意味著呼叫時也無需傳入引數
-
定義時有參,意味著呼叫時則必須傳入引數
3.5、呼叫函式的三種形式
1)語句形式
len('hello') / foo( )
- 表示式形式
res=len('hello')*10
print(res)
- 可以當做引數傳給另外一個函式
print(len("hello"))
二、函式引數
總體分為兩大類:
-
形參:在函式定義階段括號內指定的引數,稱之為形式引數,簡稱形參-》變數名
-
實參:在函式呼叫階段括號內傳入的值,稱之為實際引數,簡稱實參-》變數的值
形參與實參的關係是:在呼叫函式時,實參值會繫結給形參名,在函式呼叫完畢後解除繫結
形參系列-----
1、位置形參:在定義函式時,按照從左到右的順序依次定義的變數名,稱之為位置形參
特點:每次呼叫,必須被賦值
ef func(name,age):
print(name)
print(age)
func(1,2)
2、預設形參:在定義函式時,就已經為某個形參賦值了,稱之為預設形參
特點:呼叫函式時,可以不用為其賦值
def func(name,age=18):
print(name)
print(age)
func("egon")
func("egon",19) # 19 以呼叫的為準
& 注意 : 可以混用位置形參與預設形參,但是
1)、位置形參必須在前面
2)、預設形參的值通常應該是不可變型別
3)、預設形參的值是在函式定義階段賦值的
ef func(name,hobby,hobbies = None):
if hobbies is None:
hobbies = []
hobbies.append(hobby)
print('%s的愛好是%s' %(name,hobbies))
func('egon','read')
func('tom','play')
func('jack','music')
func('lili','eat',["movie"])
m=1111
def func(x,y,z=m):
print(x)
print(y)
print(z)
m=666
func(1,2) # m仍然是1111,以先定義的為準
實參系列-----
1、位置實參:在呼叫函式時,按照從左到右的順序依次傳入的值,稱之為位置實參
特點:按照位置為形參賦值,一 一對應
def res(name,age)
...
res('egon',18)
2、關鍵字實參:在呼叫函式時,按照key=value的形式傳值,稱之為關鍵字實參
特點:可以打亂順序,但是仍然能夠指定道姓地為指定的形參賦值
def res(name,age)
...
res(age=18,name="egon")
& 注意:可以混用位置實參與關鍵字實參,但是
1)、位置實參必須在關鍵字實參的前面
2)、不能為同一形參重複賦值
def res(name,age)
...
func("egon",age=18) # True
func(age=18,"egon") # 語法錯誤
def foo(x,y,z):
pass
foo(1,y=2,3) # 錯誤
foo(1,y=2,z=3,x=4) # 錯誤,不能重複呼叫
可變長系列-----
可變長引數指的是在呼叫函式時,傳入的實參個數不固定,對應著必須有特殊形式的形參來接收溢位的實參
實參無非兩種形式======>
溢位的位置實參--->*
溢位的位置關鍵字實參--->**
一.. ==============*與**在形參中是一種彙總行為=====================
1、*在形參中的應用: *會將溢位的位置實參合併成一個元組,然後賦值給緊跟其後的那個形參
def func(x,*args): # y = (2,3,4,5)
print(x)
print(args)
func(1,2,3,4,5)
def my_sum(*args):
res = 0
for i in args:
res += i
print(res)
my_sum(1,2) 結果為 1+2=3
2、2個* . 在形參中的應用:* *會將溢位的關鍵字實參合併成一個字典,然後賦值給緊跟其後的那個形參名
def func(x,**kwargs): # kwargs = {"a":2,"c":4,"b":3}
print(x)
print(kwargs)
func(1,a=2,b=3,c=4)
二 ..==============*與**在實參中是一種打散行為=====================
1、*在實參中的應用:*後可以跟可以被for迴圈遍歷的任意型別,*會將緊跟其後的那個值打散成位置實參
def func(x,y,z):
print(x)
print(y)
print(z)
func(*[11,22,33]) # 11,22,33
func(*"hel") # h,e,l
unc(*{"x":111,"y":2222,"z":3333}) # x,y,z
2、**在實參中的應用:**只能跟字典型別,**會將字典打散成關鍵字實參
def func(x,y,z):
print(x)
print(y)
print(z)
func(**{"x":111,"y":2222,"z":3333})
def index(x,y,z):
print(x,y,z)
def wrapper(*args,**kwargs): # args=(1,2,3,4,5,6) kwargs={"a":1,"b":2,"c":3}# index(*args,**kwargs) # index(*(1,2,3,4,5,6),**{"a":1,"b":2,"c":3})# # index(1,2,3,4,5,6,a=1,b=2,c=3)#
wrapper(1,2,3,4,5,6,a=1,b=2,c=3)
wrapper(1,y=2,z=3)
瞭解(**):命名關鍵字形參: 在*與**中間的形參稱之為命名關鍵字形參
特點: 必須按照key=value的形式傳值
def func(x,m=333,*args,y=222,z,**kwargs):
print(x)
print(args)
print(y)
print(z)
print(kwargs)
func(1,2,3,z=4,a=1,b=2,c=3)