函數參數,返回值,遞歸函數

来源:https://www.cnblogs.com/JcrLive/archive/2020/01/27/12235369.html
-Advertisement-
Play Games

函數進階 目標 函數參數和返回值的作用 函數的返回值 進階 函數的參數 進階 遞歸函數 01. 函數參數和返回值的作用 函數根據 有沒有參數 以及 有沒有返回值 ,可以 相互組合 ,一共有 4 種 組合形式 1. 無參數,無返回值 2. 無參數,有返回值 3. 有參數,無返回值 4. 有參數,有返回 ...


函數進階

目標

  • 函數參數和返回值的作用
  • 函數的返回值 進階
  • 函數的參數 進階
  • 遞歸函數

01. 函數參數和返回值的作用

函數根據 有沒有參數 以及 有沒有返回值,可以 相互組合,一共有 4 種 組合形式

  1. 無參數,無返回值
  2. 無參數,有返回值
  3. 有參數,無返回值
  4. 有參數,有返回值

定義函數時,是否接收參數,或者是否返回結果,是根據 實際的功能需求 來決定的!

  1. 如果函數 內部處理的數據不確定,就可以將外界的數據以參數傳遞到函數內部
  2. 如果希望一個函數 執行完成後,向外界彙報執行結果,就可以增加函數的返回值

1.1 無參數,無返回值

此類函數,不接收參數,也沒有返回值,應用場景如下:

  1. 只是單純地做一件事情,例如 顯示菜單
  2. 在函數內部 針對全局變數進行操作,例如:新建名片,最終結果 記錄在全局變數

註意:

  • 如果全局變數的數據類型是一個 可變類型,在函數內部可以使用 方法 修改全局變數的內容 —— 變數的引用不會改變
  • 在函數內部,使用賦值語句 才會 修改變數的引用

1.2 無參數,有返回值

此類函數,不接收參數,但是有返回值,應用場景如下:

  • 採集數據,例如 溫度計,返回結果就是當前的溫度,而不需要傳遞任何的參數

1.3 有參數,無返回值

此類函數,接收參數,沒有返回值,應用場景如下:

  • 函數內部的代碼保持不變,針對 不同的參數 處理 不同的數據
  • 例如 名片管理系統 針對 找到的名片修改刪除 操作

1.4 有參數,有返回值

此類函數,接收參數,同時有返回值,應用場景如下:

  • 函數內部的代碼保持不變,針對 不同的參數 處理 不同的數據,並且 返回期望的處理結果
  • 例如 名片管理系統 使用 字典預設值提示信息 提示用戶輸入內容
    • 如果輸入,返回輸入內容
    • 如果沒有輸入,返回字典預設值

02. 函數的返回值 進階

  • 在程式開發中,有時候,會希望 一個函數執行結束後,告訴調用者一個結果,以便調用者針對具體的結果做後續的處理
  • 返回值 是函數 完成工作後,最後 給調用者的 一個結果
  • 在函數中使用 return 關鍵字可以返回結果
  • 調用函數一方,可以 使用變數接收 函數的返回結果

問題:一個函數執行後能否返回多個結果?

示例 —— 溫度和濕度測量

  • 假設要開發一個函數能夠同時返回當前的溫度和濕度
  • 先完成返回溫度的功能如下:
def measure():
    """返回當前的溫度"""
    
    print("開始測量...")
    temp = 39
    print("測量結束...")
    
    return temp

result = measure()
print(result)
  • 在利用 元組 在返回溫度的同時,也能夠返回 濕度
  • 改造如下:
def measure():
    """返回當前的溫度"""

    print("開始測量...")
    temp = 39
    wetness = 10
    print("測量結束...")

    return (temp, wetness)

提示:如果一個函數返回的是元組,括弧可以省略

技巧

  • Python 中,可以 將一個元組 使用 賦值語句 同時賦值給 多個變數
  • 註意:變數的數量需要和元組中的元素數量保持一致
result = temp, wetness = measure()

面試題 —— 交換兩個數字

題目要求

  1. 有兩個整數變數 a = 6, b = 100
  2. 不使用其他變數,交換兩個變數的值

解法 1 —— 使用其他變數

# 解法 1 - 使用臨時變數
c = b
b = a
a = c

解法 2 —— 不使用臨時變數

# 解法 2 - 不使用臨時變數
a = a + b
b = a - b
a = a - b

解法 3 —— Python 專有,利用元組

a, b = b, a

03. 函數的參數 進階

3.1. 不可變和可變的參數

問題 1:在函數內部,針對參數使用 賦值語句,會不會影響調用函數時傳遞的 實參變數? —— 不會!

  • 無論傳遞的參數是 可變 還是 不可變
    • 只要 針對參數 使用 賦值語句,會在 函數內部 修改 局部變數的引用不會影響到 外部變數的引用
def demo(num, num_list):

    print("函數內部")

    # 賦值語句
    num = 200
    num_list = [1, 2, 3]

    print(num)
    print(num_list)

    print("函數代碼完成")


gl_num = 99
gl_list = [4, 5, 6]
demo(gl_num, gl_list)
print(gl_num)
print(gl_list)
    

問題 2:如果傳遞的參數是 可變類型,在函數內部,使用 方法 修改了數據的內容,同樣會影響到外部的數據

def mutable(num_list):

    # num_list = [1, 2, 3]
    num_list.extend([1, 2, 3])
    
    print(num_list)

gl_list = [6, 7, 8]
mutable(gl_list)
print(gl_list)

面試題 —— +=

  • python 中,列表變數調用 += 本質上是在執行列表變數的 extend 方法,不會修改變數的引用
def demo(num, num_list):

    print("函數內部代碼")

    # num = num + num
    num += num
    # num_list.extend(num_list) 由於是調用方法,所以不會修改變數的引用
    # 函數執行結束後,外部數據同樣會發生變化
    num_list += num_list

    print(num)
    print(num_list)
    print("函數代碼完成")


gl_num = 9
gl_list = [1, 2, 3]
demo(gl_num, gl_list)
print(gl_num)
print(gl_list)

3.2 預設參數

  • 定義函數時,可以給 某個參數 指定一個預設值,具有預設值的參數就叫做 預設參數
  • 調用函數時,如果沒有傳入 預設參數 的值,則在函數內部使用定義函數時指定的 參數預設值
  • 函數的預設參數,將常見的值設置為參數的預設值,從而 簡化函數的調用
  • 例如:對列表排序的方法
gl_num_list = [6, 3, 9]

# 預設就是升序排序,因為這種應用需求更多
gl_num_list.sort()
print(gl_num_list)

# 只有當需要降序排序時,才需要傳遞 `reverse` 參數
gl_num_list.sort(reverse=True)
print(gl_num_list)

指定函數的預設參數

  • 在參數後使用賦值語句,可以指定參數的預設值
def print_info(name, gender=True):

    gender_text = "男生"
    if not gender:
        gender_text = "女生"

    print("%s 是 %s" % (name, gender_text))

提示

  1. 預設參數,需要使用 最常見的值 作為預設值!
  2. 如果一個參數的值 不能確定,則不應該設置預設值,具體的數值在調用函數時,由外界傳遞!

預設參數的註意事項

1) 預設參數的定義位置
  • 必須保證 帶有預設值的預設參數 在參數列表末尾
  • 所以,以下定義是錯誤的!
def print_info(name, gender=True, title):
2) 調用帶有多個預設參數的函數
  • 調用函數時,如果有 多個預設參數需要指定參數名,這樣解釋器才能夠知道參數的對應關係!
def print_info(name, title="", gender=True):
    """

    :param title: 職位
    :param name: 班上同學的姓名
    :param gender: True 男生 False 女生
    """

    gender_text = "男生"

    if not gender:
        gender_text = "女生"

    print("%s%s 是 %s" % (title, name, gender_text))


# 提示:在指定預設參數的預設值時,應該使用最常見的值作為預設值!
print_info("小明")
print_info("老王", title="班長")
print_info("小美", gender=False)

3.3 多值參數(知道)

定義支持多值參數的函數

  • 有時可能需要 一個函數 能夠處理的參數 個數 是不確定的,這個時候,就可以使用 多值參數
  • python 中有 兩種 多值參數:
    • 參數名前增加 一個 * 可以接收 元組
    • 參數名前增加 兩個 * 可以接收 字典
  • 一般在給多值參數命名時,習慣使用以下兩個名字
    • *args —— 存放 元組 參數,前面有一個 *
    • **kwargs —— 存放 字典 參數,前面有兩個 *
  • argsarguments 的縮寫,有變數的含義
  • kwkeyword 的縮寫,kwargs 可以記憶 鍵值對參數
def demo(num, *args, **kwargs):

    print(num)
    print(args)
    print(kwargs)


demo(1, 2, 3, 4, 5, name="小明", age=18, gender=True)

提示:多值參數 的應用會經常出現在網路上一些大牛開發的框架中,知道多值參數,有利於我們能夠讀懂大牛的代碼

多值參數案例 —— 計算任意多個數字的和

需求

  1. 定義一個函數 sum_numbers,可以接收的 任意多個整數
  2. 功能要求:將傳遞的 所有數字累加 並且返回累加結果
def sum_numbers(*args):

    num = 0
    # 遍歷 args 元組順序求和
    for n in args:
        num += n

    return num

print(sum_numbers(1, 2, 3))

元組和字典的拆包(知道)

  • 在調用帶有多值參數的函數時,如果希望:
    • 將一個 元組變數,直接傳遞給 args
    • 將一個 字典變數,直接傳遞給 kwargs
  • 就可以使用 拆包,簡化參數的傳遞,拆包 的方式是:
    • 元組變數前,增加 一個 *
    • 字典變數前,增加 兩個 *
def demo(*args, **kwargs):

    print(args)
    print(kwargs)


# 需要將一個元組變數/字典變數傳遞給函數對應的參數
gl_nums = (1, 2, 3)
gl_xiaoming = {"name": "小明", "age": 18}

# 會把 num_tuple 和 xiaoming 作為元組傳遞個 args
# demo(gl_nums, gl_xiaoming)
demo(*gl_nums, **gl_xiaoming)

04. 函數的遞歸

函數調用自身的 編程技巧 稱為遞歸

4.1 遞歸函數的特點

特點

  • 一個函數 內部 調用自己
    • 函數內部可以調用其他函數,當然在函數內部也可以調用自己

代碼特點

  1. 函數內部的 代碼 是相同的,只是針對 參數 不同,處理的結果不同
  2. 參數滿足一個條件 時,函數不再執行
    • 這個非常重要,通常被稱為遞歸的出口,否則 會出現死迴圈

示例代碼

def sum_numbers(num):

    print(num)
    
    # 遞歸的出口很重要,否則會出現死迴圈
    if num == 1:
        return

    sum_numbers(num - 1)
    
sum_numbers(3)

4.2 遞歸案例 —— 計算數字累加

需求

  1. 定義一個函數 sum_numbers
  2. 能夠接收一個 num 的整數參數
  3. 計算 1 + 2 + ... num 的結果
def sum_numbers(num):

    if num == 1:
        return 1
    
    # 假設 sum_numbers 能夠完成 num - 1 的累加
    temp = sum_numbers(num - 1)

    # 函數內部的核心演算法就是 兩個數字的相加
    return num + temp

print(sum_numbers(2))

提示:遞歸是一個 編程技巧,初次接觸遞歸會感覺有些吃力!在處理 不確定的迴圈條件時,格外的有用,例如:遍歷整個文件目錄的結構


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ![](https://img2018.cnblogs.com/blog/1853166/202001/1853166-20200126143013655-154923141.png) ![](https://img2018.cnblogs.com/blog/1853166/202001/18531... ...
  • 滿足最小分組的長度為其他分組的整數倍 ...
  • ![](https://img2018.cnblogs.com/blog/1853166/202001/1853166-20200126115527094-488420466.png)![](https://img2018.cnblogs.com/blog/1853166/202001/185316... ...
  • jQuery 滑動方法 通過 jQuery,您可以在元素上創建滑動效果。 jQuery 擁有以下滑動方法: slideDown() slideUp() slideToggle() jQuery slideDown() 方法 jQuery slideDown() 方法用於向下滑動元素。 語法: $(s ...
  • javascript export default (str) = { // 建立數據結構,堆棧,保存數據 let r = [] // 給定任意子輸入都返回第一個符合條件的子串 let match = (str) = { let j = str.match(/^(0+|1+)/)[0] let o ...
  • 第一種 第二種 第三種 第四種 ...
  • 互聯網那些事之數據丟失 本系列故事的所有案例和解決方案只是筆者以前在互聯網工作期間的一些事例,僅供大家參考,實際操作應該根據業務和項目情況設計,歡迎大家留言提出寶貴的意見 背景 小王和小明分別維護分散式系統中A、b兩個服務,有一個場景是 A服務會向B服務通過MQ發送事件並且推送用戶信息,然後B服務保 ...
  • 面向對象編程 —— Object Oriented Programming 簡寫 OOP 01. 面向對象基本概念 我們之前學習的編程方式就是 面向過程 的 面相過程 和 面相對象,是兩種不同的 編程方式 對比 面向過程 的特點,可以更好地瞭解什麼是 面向對象 1.1 過程和函數(科普) 過程 是早 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...