筆者:風起怨江南 出處:https://blog.csdn.net/JackMengJin 筆者原創,文章歡迎轉載,如果喜歡請點贊+關注,感謝支持!
本篇主要講解Python函數參數的重要知識點,上一篇中涉及到函數的定義等相關知識點,回顧請點鏈接->傳送門。
目錄
函數參數的定義和用法
函數參數前先回顧下函數的定義和調用。
一、函數定義
1.1 什麼是函數
上一篇內容講到了函數的概念:
函數是組織好的,可重複使用的,用來實現單一,或相關聯功能的代碼段。更直白的話說就是:函數是當輸入一定的數據以後,
能根據裏面的執行步驟,可以算出另一些數據的值。同時可以得到數據,獲取輸出值。
那麼其實調用或自定義足夠多的函數後,會對函數有更深刻的理解:
函數就是存儲指定的程序(代碼),或者把函數看成一個盒子,外面的代碼是另一個盒子,相互之間沒有關係。Python框架的源碼都是基於函數。
1.2 函數的表示
換而言之,函數就是一個一段程序,一段代碼,我們需要用函數去達到所期望的效果,所以將代碼封裝爲函數,從而可以重複的去使用。
函數的表示:
def add(a,b):
'''這是文檔字符串,告訴函數幹嘛用的'''
#函數體
c = a + b
return c
def 頂行寫, 加定義的函數名(括號裏要傳的參數)冒號結尾:
'''空4格,這裏要寫函數的文檔字符串,用來描述函數的作用'''
這裏是代碼塊,也就是函數體。
return 返回一個值。
1.3 函數的調用
函數調用的概念:函數調用就會執行函數內部的邏輯。
先定義一個作用爲計算器的函數,傳入兩個參數並計算:
def calculator(num1,num2):
'''文檔字符串
函數的作用:該函數通過輸入兩個參數,並根據輸入的數字:1表示加、2表示減、3表示乘、4表示除,來計算求結果
返回值:操作後的值
'''
#while循環判斷輸入的數字是否爲1-4,如果不是,重新輸入
while True:
sign = input('請輸入數字(1表示加、2表示減、3表示乘、4表示除):')
if sign == '1' or sign == '2' or sign == '3' or sign == '4':
break
else:
print('輸入操作錯誤,請輸入數字1-4。')
#定義變量num_sum爲計算結果,先賦值0
num_sum = 0
if sign == '1': #當輸入數字爲1時,相加
num_sum = num1 + num2
elif sign == '2': #當輸入數字爲2時,相減
num_sum = num1 - num2
elif sign == '3': #當輸入數字爲3時,相乘
num_sum = num1 * num2
else: #當輸入數字爲4時,相除,同時判斷如果被除數爲0時,退出計算
if num2 == 0:
return print('被除數不能爲0,退出計算,返回None!')
num_sum = num1 / num2
return num_sum
自定義完calculator()函數之後如何去驗證和調用這個函數呢?
#輸入的值轉換爲浮點類型
num1 = float(input('請輸入第一個需要計算的數字:'))
num2 = float(input('請輸入第二個需要計算的數字:'))
#聲明變量,用來存儲函數計算的值,並打印
num_sum = calculator(num1,num2)
print('經過計算,最後的結果爲:',num_sum)
運行後的結果:
請輸入第一個需要計算的數字:100
請輸入第二個需要計算的數字:25
請輸入數字(1表示加、2表示減、3表示乘、4表示除):4
經過計算,最後的結果爲: 4.0
可以看到,在函數中傳入兩個參數(也就是兩個變量),通過運算後,返回出一個值,再通過print打印將返回的值打印出來。
所以函數的調用方法:
函數名(參數)
在定義完函數後,直接用函數名加里面的參數內容,就可以直接去調用這個函數。
關於函數的參數部分在第二節具體講解。
函數裏調用函數?
在一個函數裏調用另一個函數,函數調用就會執行函數內部的邏輯。當內部邏輯裏調用另一個函數時,再在去讀調用的那個函數裏內部的邏輯。
舉個簡單的例子:
#定義一個函數,用於比較傳入數值的大小,返回值爲比較大的數
def compareNum(num1,num2):
'''比較大小,返回較大值'''
max_num = max(num1,num2)
return max_num
#定義另一個函數,根據傳入的兩個數值,選出最大的一個數值,並打印出相應行數的hello world
def powerNum(num1,num2):
'''傳入的兩個數值,選出最大的一個數值,並打印出相應行數的hello world'''
max_num = compareNum(num1,num2)
for i in range(max_num):
print('hello world!')
可以看到第二個函數中調用了第一個函數,那麼傳入兩個變量。運行下會有什麼效果:
num1 = int(input('數字1:'))
num2 = int(input('數字2:'))
powerNum(num1,num2)
數字1:2
數字2:5
hello world!
hello world!
hello world!
hello world!
hello world!
這裏函數調用函數有什麼需要注意的地方?如果將上面的兩個函數位置調換一下,會報錯麼?
#定義另一個函數,根據傳入的兩個數值,選出最大的一個數值,並打印出相應行數的hello world
def powerNum(num1,num2):
'''傳入的兩個數值,選出最大的一個數值,並打印出相應行數的hello world'''
max_num = compareNum(num1,num2)
for i in range(max_num):
print('hello world!')
#定義一個函數,用於比較傳入數值的大小,返回值爲比較大的數
def compareNum(num1,num2):
'''比較大小,返回較大值'''
max_num = max(num1,num2)
return max_num
num1 = int(input('數字1:'))
num2 = int(input('數字2:'))
powerNum(num1,num2)
數字1:1
數字2:2
hello world!
hello world!
很顯然沒有報錯,這是跟python的運行機制有關,下面具體分析一下錯誤情況。
錯誤的調用順序:
#定義另一個函數,根據傳入的兩個數值,選出最大的一個數值,並打印出相應行數的hello world
def powerNum(num1,num2):
'''傳入的兩個數值,選出最大的一個數值,並打印出相應行數的hello world'''
max_num = compareNum(num1,num2)
for i in range(max_num):
print('hello world!')
num1 = int(input('數字1:'))
num2 = int(input('數字2:'))
powerNum(num1,num2)
#定義一個函數,用於比較傳入數值的大小,返回值爲比較大的數
def compareNum(num1,num2):
'''比較大小,返回較大值'''
max_num = max(num1,num2)
return max_num
我將調用函數的位置放在了函數的前面,運行會怎樣呢?
數字1:1
數字2:2
Traceback (most recent call last):
File "E:/MyLife/網課學習/檸檬班/作業/博客/demo_new.py", line 19, in <module>
powerNum(num1,num2)
File "E:/MyLife/網課學習/檸檬班/作業/博客/demo_new.py", line 13, in powerNum
max_num = compareNum(num1,num2)
NameError: name 'compareNum' is not defined
果不其然報錯了,NameError: name 'compareNum' is not defined,原因是爲什麼?
其實原因還是和python的運行機制有關,python在運行的時候,先去根據順序去執行每一條頂行寫的代碼,當執行到powerNum(num1,num2)調用函數這一行時,進入到powerNum函數體的內部,再去調用裏面的函數compareNum函數。此時python會發現,咦?怎麼沒有 compareNum這個函數呢?所以便沒有繼續去執行下面的代碼,而是直接報錯,停止運行。
總結:函數調用函數的時候,一定要注意先後順序,可以用打斷點和debug的方法去一行一行理解。
二、函數參數的定義
講函數參數定義前,先思考一個問題,爲什麼要給函數加參數?這裏先賣個關子,等了解所有函數參數的定義後自然而然就明白了。函數的參數有哪些呢?
2.1 形式參數
形式參數是在函數定義的時候,函數名括號裏的內容,可以理解爲是變量名。
比如上面例子中自定義的函數:
def compareNum(num1,num2):
這裏的num1和num2就是形式參數,簡稱形參。
2.2 實際參數
實際參數就是函數調用的時候函數名括號裏的內容。
num1 = int(input('數字1:'))
num2 = int(input('數字2:'))
powerNum(num1,num2)
由於已經的值函數的目的是爲了存儲程序,而且變量都是會變的量,所以在定義函數的時候,變量一般放在外面,在調用
的時候在將變量傳入到函數中,所以這裏的變量也就是說所的實際參數。
這裏的num1和num2,就是實際參數,簡稱爲實參。
2.3 位置參數
理解了形式參數和實際參數的含義,再去理解位置參數(positional argument)就比較簡單了。
位置參數其實就是表示形式參數和實際參數之間的關係,要按順序對應。這裏需要注意的是,所謂的對應指的是一一對
應,不能多不能少,順序也要剛剛好。
def compareNum(num1,num2):
'''比較大小,返回較大值'''
max_num = max(num1,num2)
return max_num
compareNum(1,2,3)
如果實際參數和形式參數有差別,就會報錯:
compareNum(1,2,3)
TypeError: compareNum() takes 2 positional arguments but 3 were given
2.4 關鍵字參數
關鍵字參數(keyword argument)比較好理解了,先看例子:
def get_name(firstname,middle,lastname):
'''返回名字'''
return firstname + middle + lastname
print(get_name('羅',middle='志',lastname='翔'))
羅志翔
這裏可以看到關鍵字參數其實就是在實際參數前面加上形式參數。如果沒有關鍵字參數,容易搞混位置,不容易弄清每個形式
參數的意思。而加了關鍵字參數後,可以提高函數調用的可讀性,也更加容易理解實際參數的意義。
那麼關鍵字到底怎麼來的?
而關鍵字必須要在形式函數裏選,而關鍵字的名字就是形式參數。
關鍵字參數和位置參數的區別:相對於位置參數來講,對於參數比較多的情況下,使用關鍵字參數就不需要去比較了,直接就知
道表示什麼意思。
同時關鍵字參數區別位置參數的地方:可以不按照順序進行調用,可以交換順序。
def get_name(firstname,middle,lastname):
'''返回名字'''
return firstname + middle + lastname
print(get_name('羅',lastname='翔',middle='志'))
羅志翔
到這裏有沒有發現,關鍵字參數特別像字典吧?只需要確定形式參數(key),位置不管怎麼改變(字典是無序的)都不影響最
後的結果(鍵值對)。
關鍵字函數的優點:
- 可讀性
- 不按照順序,可以不按照套路出牌
需要注意的地方——位置:
def get_name(firstname,middle,lastname):
'''返回名字'''
return firstname + middle + lastname
print(get_name(lastname='翔','羅',middle='志'))
print(get_name(lastname='翔','羅',middle='志'))
^
SyntaxError: positional argument follows keyword argument
如果將關鍵字參數放在位置參數的前面,會報錯!SyntaxError: positional argument follows keyword argument
關鍵字參數要放到位置參數後面。
關鍵字參數作用:可以交換參數的順序,並且提高可讀性難度內容
2.4 默認參數
默認參數的定義:默認參數就是在在函數定義的時候,給參數一個缺省值。
默認參數的表示:
def get_name(firstname,middle='志',lastname='翔'):
'''返回名字'''
return firstname + middle + lastname
print(get_name('羅','志','翔'))
羅志翔
如果沒有傳入該參數的實際參數時:
def get_name(firstname,middle='志',lastname='翔'):
'''返回名字'''
return firstname + middle + lastname
print(get_name('羅'))
羅志翔
這裏看到返回的是缺省值,也就是默認參數。
默認參數的概念:
- 當在函數調用的時候,沒有傳入該參數的實際參數時,則直接使用缺省值
- 如果調用函數的時候,傳入了這個實際參數,則默認值不會生效
def get_name(firstname,middle='志',lastname='翔'):
'''返回名字'''
return firstname + middle + lastname
print(get_name('羅','小','豬'))
羅小豬
默認參數的優點不難得出:
- 可以簡化函數調用的過程,只需要傳入少量的參數就可以實現調用過程。
這裏引申一下print()這個內置函數:
爲什麼每次print的時候都是下一行開始的?就是因爲print函數有默認參數,所以缺省狀態下就是換行。
end='\n'
默認參數的位置:
其實還是位置問題,位置參數必須放在前面,默認參數需要放在位置參數的後面!
默認參數的總結:
- 默認參數值在函數定義的時候,給參數一個缺省值。
- 當在函數調用的時候,沒有傳入該參數的實際參數時,則直接使用缺省值。
- 如果調用函數的時候,傳入了這個實際參數,則默認值不會生效。
- 好處是可以簡化函數調用的過程,只需要傳入少量的參數就可以實現調用過程。
2.5不定長參數——位置不定長參數
可變長參數有兩種形式*args和**kwargs。
可變長參數的定義:直譯的意思就是可變長參數的定義,也就是傳入的實際參數是可變長度。*表示位置不定長參數,**表示關鍵字不定長參數(keyword args )。
- 一個*表示位置不定長參數,通常是*args表示,但起什麼名字都是可以的。
- 另一個**表示關鍵字不定長參數,通常用**kwargs表示。
def get_name(*name):
'''打印名字'''
print(name)
get_name('羅','小','豬')
('羅', '小', '豬')
可以看到位置不定長參數打印出來是個元組類型。
雖然位置不定長參數也是位置參數,但位置參數是要在*位置參數前面的,這其實挺好去理解的:如果不定長參數在前面,位置
參數在後面,那麼實際參數無論是什麼,都表示的是不定長參數,而後面的位置參數永遠也傳不了參數。
那麼可不可以有兩個位置不定長參數?
不可以:
def get_name(*name,*name1):
^
SyntaxError: invalid syntax
所以在一個函數裏只能有一個位置不定長參數,同樣也只能有一個關鍵字不定長參數。
2.6不定長參數——關鍵字不定長參數
關鍵字不定長參數其實就是在變量前打**號,通常用**kwargs表示。
def get_name(*names,**kewargs):
print(names)
print(kewargs)
get_name('羅','小','豬')
('羅', '小', '豬')
{}
通過打印可以看到關鍵字不定長參數是字典數據類型。
所以得到一個概念:位置不定長參數和關鍵字不定長參數在函數裏分別是用元組和字典去表示。
def get_name(**kewargs):
print(kewargs)
get_name(middle = '志')
{'middle': '羅'}
這裏的關鍵字是在在形式參數裏找,結果發現形式參數裏沒有middle這個參數,由於找不到,就會將middle存到key裏。
不定長參數總結:
位置不定長參數有順序的要求,是一一對應的,獲取*args得到的是元組。
關鍵字參數可以打亂參數,但需要加個key ,獲取**kwargs到的是字典。
需要注意位置:關鍵字參數是不能放在位置參數前面!
位置參數 > *位置參數 > **關鍵字參數。
2.6 函數參數意義
通過上面的內容,可以發現函數的目的就是爲了存儲程序。
函數用來存儲程序,就是爲了一遍一遍的重複去使用。也就是說所的實際參數, 實際參數就是變量。所以要把數據都提取出
來,作爲變量放在參數裏面。之所以不把變量放在函數裏面,是因爲函數一般不存儲數據,函數只存儲程序!
當有變量發生變化時,函數裏的內容也會發生變化。把變量提取出來,作爲一個形式參數,放在函數參數裏去,這就是函數參數
的意義。
下一篇內容爲函數的返回值和函數的作用域,敬請期待。
以上是《Python學習11:函數參數的定義和用法》的所有內容,更多python學習請繼續關注我的博客——風起怨江南(傳送
門),不定期更新,原創不易,如果喜歡請點贊和關注,謝謝大家的支持!
想獲得免費的學習資料請添加微信公衆號——風起怨江南,非常感謝大家的關注和支持!