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

函數進階

目標

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

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

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

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

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

  1. 若是函數 內部處理的數據不肯定,就能夠將外界的數據以參數傳遞到函數內部
  2. 若是但願一個函數 執行完成後,向外界彙報執行結果,就能夠增長函數的返回值

1.1 無參數,無返回值

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

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

注意:編程

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

1.2 無參數,有返回值

此類函數,不接收參數,可是有返回值,應用場景以下:網絡

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

1.3 有參數,無返回值

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

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

1.4 有參數,有返回值

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

  • 函數內部的代碼保持不變,針對 不一樣的參數 處理 不一樣的數據,而且 返回指望的處理結果
  • 例如 名片管理系統 使用 字典默認值提示信息 提示用戶輸入內容
    • 若是輸入,返回輸入內容
    • 若是沒有輸入,返回字典默認值

02. 函數的返回值 進階

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

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

示例 —— 溫度和溼度測量

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

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

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

    return (temp, wetness)

提示:若是一個函數返回的是元組,括號能夠省略blog

技巧排序

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

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

相關文章
相關標籤/搜索