天天看點

python-函數進階-筆記

函數進階

目标

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

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​

    ​ —— 存放 字典 參數,前面有兩個 ​

    ​*​

  • ​args​

    ​ 是

    arguments

    的縮寫,有變量的含義
  • ​kw​

    ​ 是

    keyword

    的縮寫,

    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))      

繼續閱讀