一、Python函數的形式
def function_name (參數, ...) -> return value_type:# 函數體return value# 看具體需求# 如果沒有return語句,函數執行完畢后也會返回結果# 只是結果為None。return None可以簡寫為return
1. Python的返回值
? ? ? ? 在Python3中,提供了可以標注函數返回值的類型的功能,但Python是動態類型語言對返回值的類型標注不會像C++這種靜態類型語言那樣進行嚴格的類型檢查和限制,所以我們可以認為返回值只是給程序員自己看著方便,在語法不會檢查。
返回值標注的作用:
- 增強代碼的可讀性:標注返回值類型可以讓其他開發者在閱讀代碼時更清楚地理解函數的預? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?期輸出。
- 作為文檔:有助于為使用該函數的其他開發者提供明確的信息,減少誤解和錯誤使用。
- 輔助靜態類型檢查工具:雖然 Python 本身不強制檢查,但結合一些第三方的靜態類型檢查? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 工具(如 mypy),可以在一定程度上進行類型檢查,提前發現潛在? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 的類型錯誤。
【C++】
????????在C++中,函數的返回值類型是必須標注的,靜態類型語言必須保證接收函數返回值的時候數據類型是匹配的
2.?Python函數返回多個值
????????返回的是一個元組對象,在語法上,返回一個tuple可以省略括號,而多個變量可以同時接收一個tuple,按位置賦給對應的值,所以,Python的函數返回多值其實就是返回一個tuple,但寫起來更方便;
????????而C++中返回多個值,可以采用輸出型參數或者是返回一個類對象
def function_name (參數, ...):return a, b ,c
????????如果函數的返回值我們只使用一部分,不關注其他的返回值,可以使用占位符 ‘ _ ’來進行占位
def func():return 1, 2, 3_, _, a = func()
print('a = %d' % a)

3. 空函數
def func():pass
二、Python函數的參數
1. 位置參數:
與C++一致,實參的位置與形參的位置相匹配
2. 缺省參數:
與C++一致,形參有缺省參數,可以不傳參也可以傳參
設置缺省參數的規則:
- 參數在前,缺省參數在后
- 當函數有多個參數時,在傳參時把變化大的參數放在前面,變化小的參數放在后面(變化小的參數可以作為缺省參數)
- 必須指向不可變對象
為什么默認參數在后?
????????當默認參數在前時,我們傳入一個實參,就會發生疑問,這個實參是給缺省參數的?還是給參數的?因為可以一方面通過位置參數來,另一方面可以通過缺省參數來,所以就會產生二義性,為了防止此類事件的發生,規定缺省參數要在參數的后面。
缺省參數的坑:為什么要指向不可變對象?
Python函數缺省參數的 “ 坑 ” (與C++對比學習)-CSDN博客
3. 可變參數:
????????支持傳入任意個參數,函數內部接收到的是一個元組tuple(在返回值和參數這里使用元組主要是保證傳入或輸出的對象的安全性,防止惡意篡改)
使用形式:
def func(*num):s = 0for i in num:s += ireturn sret = func(1, 2, 3, 4, 5, 6, 7, 8)
print(ret)
4. 顯示命名參數
? ? ? ? 按照形參名字傳參,無視位置,一般搭配缺省參數使用
使用形式:
def func(id_num, name='dd', age=20):print('id:', id_num, '\nname:', name, '\nage:', age)func(1, age=18)
5. 關鍵字參數
????????關鍵字參數允許我們傳入任意個含有參數名的參數,這些關鍵字參數會在函數內部自動組裝為一個dict。
使用形式:
def func(name, age, **kw):print('name:', name, '\nage:', age, '\nothers:', kw)func('dd', 20, city='上海', work='程序員')

簡化版本:
????????**dic表示把該字典中的所有key:value用關鍵字參數傳入函數的**kw中,需要注意的是kw獲得的dict是dic的一份拷貝,對kw的改動不會影響函數外的dic
def func(name, age, **kw):print('name:', name, '\nage:', age, '\nothers:', kw)dic = {'city': '上海', 'work': '程序員'}
func('yy', 18, **dic)

6. 命名關鍵字參數
????????只可以傳入命名關鍵字參數后的關鍵字參數
使用形式:
- 特殊分隔符 * 后面的參數被視為命名關鍵字參數
- 如果函數定義中有可變參數,后面跟著的命名關鍵字參數就不需要特殊分隔符*
- 命名關鍵字參數必須傳入參數名
def fun(name, age, *, city, work):print('name:', name, '\nage:', age, '\ncity:', city, '\nwork', work)fun('wyd', 20, city='上海', work='程序員')
7. 各種參數可以組合使用
參數定義的順序必須是:必選參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數
三、遞歸函數
????????與C++一致,自己調用自己,但是要防止棧溢出,采用的方法是尾遞歸,保證每次函數調用只占用一個棧幀。
如計算n的階乘:
采用遞歸的方式:
n值過大,則會導致棧空間溢出,因為下面這種是不斷調用遞歸,會不斷的壓棧,從而導致棧空間不足
def fact(n):if n == 1:return nreturn n * fact(n-1)
采用尾遞歸的方式:
????????每次只用一個棧幀,尾遞歸的好處就是最外層的函數調用完自身就會銷毀函數棧幀,從而保證每次只使用一個棧幀,遺憾的是,大多數編程語言沒有針對尾遞歸做優化,Python解釋器也沒有做優化,所以,即使把上面的
fact(n)函數改成尾遞歸方式,也會導致棧溢出。
def fact_operator(n, s):if n == 1:return sreturn fact_operator(n - 1, n * s)def fact(n):return fact_operator(n, 1)