1. 程式人生 > 實用技巧 >python 之使用者自定義函式

python 之使用者自定義函式

什麼是函式?

函式無非就是將程式碼塊進行封裝,想用的時候拿來用,減少程式碼量,提高效率。

函式的定義

定義一個函式需要:

1.def關鍵字,def 後面空一格輸入函式名稱,函式命名時儘量簡短,且具有意義,能通過函式名窺見該函式實所實現的功能,函式名稱後面緊跟著一對英文圓括號()和英文冒號:

def關鍵字、函式名、括號、冒號缺一不可

2.括號裡面存放參數,根據需要可傳可不傳

3.一般使用三重引號註釋函式所實現功能,並放於第一行(根據編碼者習慣可寫可不寫)

4.冒號以下都是函式內容

5.return 可寫可不寫,根據實際情況,若不填寫時,該函式無返回值

def my_fun(parameters):
    
""" 實現XXXXX功能 :return: """ Function body return expression

定義一個簡單的函式

def marks():
    """
    分數校驗
    :return:
    """
    mark = float(input("請輸入分數:"))
    if mark < 60:
        return False
    else:
        return True

函式定義後不會執行,需要呼叫才會去執行

函式的呼叫

def sub(a, b):
    """
    實現減法
    :param a:
    :param b:
    :return:
    
""" return a - b result = sub(2, 5) print(result)
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
-3

或者由其他函式呼叫執行

import random
import string
import hashlib


def random_str(number):
    """
    生成隨機碼
    :param number:
    :return:
    """
    code = ''.join(random.sample(string.digits + string.ascii_letters, int(number)))
    
return code def md5_str(number): """ md5加密 :param number: :return: """ md5_data = hashlib.md5() md5_data.update(random_str(number).encode()) # 呼叫random_str()函式生成隨機數 sign = md5_data.hexdigest() return sign if __name__ == '__main__': string = md5_str(8) print(string)
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
345b36fc3ee89f786bc122cb3f8c26f2

引數使用

上面的例子中已用到了引數,在python實際使用中,引數分為形參、實參

形參:定義函式時傳遞的引數

實參:呼叫函式時傳遞的引數

def len_str(data):  # 形參 data
    """
    獲取字串長度
    :param data:
    :return:
    """
    count = 0
    for i in data:
        count += 1
    return count


print(len_str("If you plant a melon, you get a melon"))  # 傳入實參
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
37

位置引數(必備引數)

呼叫時傳入的引數必須與宣告中的引數一一對應,包括位置、數量、引數型別

def max_data(da):
    """
    獲取列表中最大值
    :param da:
    :return:
    """
    for i in range(len(da) - 1):
        for j in range(len(da)-1 - i):
            if da[j] > da[i]:
                temp = da[j]
                da[j] = da[j+1]
                da[j+1] = temp
    return da[len(da) - 1]


print(max_data())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
Traceback (most recent call last):
  File "D:/demo/funtion_1.py", line 63, in <module>
    print(max_data())
TypeError: max_data() missing 1 required positional argument: 'da'
def student(name, age):
    stu = {"張三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "該考生存在"
     

print(student(19, "王二"))  # name 對應19, age 對應王二
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
查無此人
def student(name, age):
    stu = {"張三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "該考生存在"


print(student("王二", 19))  # name 對應王二, age 對應19
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
該考生存在

關鍵字引數

關鍵字引數是指在呼叫時,使用形參名+傳入的引數值(parameter1=value1,parameter2=value2),使用關鍵字引數時不需要與宣告中的位置對應

def student(name, age):
    stu = {"張三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "該考生存在"


print(student(age=19, name="王二"))  # name、age 位置可不對應
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
該考生存在

位置引數與關鍵字引數混合使用

混合使用時,位置引數一定要在關鍵字引數前,不然程式報錯,不可執行

def student(name, age):
    stu = {"張三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "該考生存在"


print(student(age=19, "王二"))  # 當關鍵字引數在位置引數前時丟擲"位置引數必須在關鍵字引數前"
  File "D:/demo/funtion_1.py", line 73
    print(student(age=19, "王二"))  # 當關鍵字引數在位置引數前時丟擲"位置引數必須在關鍵字引數前"
                         ^
SyntaxError: positional argument follows keyword argument
def student(name, age):
    stu = {"張三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "該考生存在"


print(student("王二", age=19,))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
該考生存在

關鍵字引數與位置引數混合使用,容易出現一個坑,TypeError: xxxxx() got multiple values for argument xxxxx'

def student(name, age):
    stu = {"張三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "該考生存在"


print(student(19, name="王二"))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
Traceback (most recent call last):
  File "D:/demo/funtion_1.py", line 73, in <module>
    print(student(19, name="王二"))
TypeError: student() got multiple values for argument 'name'

預設引數

預設引數是指在定義時傳入引數值,呼叫時未傳入引數則使用預設傳入的引數值,否則使用呼叫傳入的引數值



def marks(mark=60):
    mar = float(input("請輸入你的分數"))
    if mar > mark:
        return "及格線為: %s, 你及格了" % mark
    else:
        return "及格線為: %s, 你需要補考" % mark


print(marks(85))  # 傳入引數,此時使用呼叫時傳入的引數值
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
請輸入你的分數80
及格線為: 85, 你需要補考
def marks(mark=60):
    mar = float(input("請輸入你的分數"))
    if mar > mark:
        return "及格線為: %s, 你及格了" % mark
    else:
        return "及格線為: %s, 你需要補考" % mark


print(marks())  # 不傳入引數,此時使用定義時傳入的引數值
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
請輸入你的分數80
及格線為: 60, 你及格了

動態引數

動態引數又稱為不定長引數,在使用時,根據需要可以傳入任意個引數,動態引數有兩種形式,*args, **kwargs,引數間的位置排序為:位置引數、預設引數、*args動態引數、**kwargs動態引數、關鍵字引數

*args: 表示接受任意多個實際引數將其放到一個元組中,如果引數是個列表,會將整個列表當做一個引數傳入

def marks(*args):
    print(args)
    for i in args:
        print(i)


(marks(["張三", "李四", "王二", "麻子"], [50, 50, 70, 90]))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
(['張三', '李四', '王二', '麻子'], [50, 50, 70, 90])
['張三', '李四', '王二', '麻子']
[50, 50, 70, 90]

以上是將列表當成一個引數,若要分解成多個引數,呼叫時可以在引數前加 *,也稱為解包(適用於任何序列型別資料物件)

def marks(*args):
    print(args)
    for i in args:
        print(i)


(marks(*["張三", "李四", "王二", "麻子"], *[50, 50, 70, 90]))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
('張三', '李四', '王二', '麻子', 50, 50, 70, 90)
張三
李四
王二
麻子
50
50
70
90
def marks(*args):
    print(args)
    for i in args:
        print(i)


(marks(*{"張三": 95, "李四": 20, "王二": 88, "麻子": 91}))  # 將字典中的key作為引數
('張三', '李四', '王二', '麻子')
張三
李四
王二
麻子

**kwargs:表示接受任意多個實際引數將其放到一個字典中,類似關鍵字引數

def marks(**kwargs):
    print(kwargs)
    for name, mark in kwargs.items():
        print(name, ":", mark)


(marks(張三=90, 李四=20))  # 通過關鍵字傳入
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
{'張三': 90, '李四': 20}
張三 : 90
李四 : 20
def marks(**kwargs):
    print(kwargs)
    for name, mark in kwargs.items():
        print(name, ":", mark)


(marks(**{"張三": 95, "李四": 20, "王二": 88, "麻子": 91}))  # 通過字典傳入,在引數前加入**,函式會把dict中所有鍵值對轉換為關鍵字引數傳進去
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
{'張三': 95, '李四': 20, '王二': 88, '麻子': 91}
張三 : 95
李四 : 20
王二 : 88
麻子 : 91

*args, **kwagrs混合使用

def persons(name, age, *args, **kwargs):
    print(args)
    print(kwargs)
    infos = ''
    if "" in name or age < 20:
        if kwargs['address'] == "深圳":
            for info in args:
                infos += info
            for k, v in kwargs.items():
                print(name, "基礎資料有", k, ":", v)
            print(name, "年齡在20的深圳小青年,其他資訊有", infos)


persons("王二", 19, "文藝", "搖滾", address="深圳", job="student")
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
('文藝', '搖滾')
{'address': '深圳', 'job': 'student'}
王二 基礎資料有 address : 深圳
王二 基礎資料有 job : student
王二 年齡在20的深圳小青年,其他資訊有 文藝搖滾

函式變數作用域

根據變數的定義位置,決定變數的作用範圍

區域性變數:定義在函式內部的變數,只在函式內部有效,執行完後,區域性變數會被釋放,無法再次訪問

全域性變數:定義在整個檔案層次上,可以在整個程式範圍內訪問

def sum(a, b):
    count = a + b
    return count  # count 區域性變數


print(sum(1, 4))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
5
guess = -10   # 全域性變數


def compare():
    times = 3
    while times > 0:
        value = float(input("請輸入你所猜數字, 你還有%s次機會" % times))
        if value == guess:
            return "恭喜,猜對啦"
        else:
            times -= 1
    return "很遺憾,你的次數用完啦"


print(compare())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
請輸入你所猜數字, 你還有3次機會3
請輸入你所猜數字, 你還有2次機會0
請輸入你所猜數字, 你還有1次機會9
很遺憾,你的次數用完啦

嘗試在函式內修改全域性變數

guess = -10   # 全域性變數


def compare():
    times = 3
    while times > 0:
        value = float(input("請輸入你所猜數字, 你還有%s次機會" % times))
        if value == guess:
            return "恭喜,猜對啦"
        else:
            guess = 1
            times -= 1
    return "很遺憾,你的次數用完啦"


print(compare())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
請輸入你所猜數字, 你還有3次機會24
Traceback (most recent call last):
  File "D:/demo/funtion_1.py", line 135, in <module>
    print(compare())
  File "D:/demo/funtion_1.py", line 127, in compare
    if value == guess:
UnboundLocalError: local variable 'guess' referenced before assignment

在函式內部修改全域性變數報錯了,這是因為,Python 的直譯器會預設函式內部的變數為區域性變數,然而區域性變數 guess 又沒有宣告,因此就無法執行相關操作。那麼如果要在函式內更改全域性變數呢?

這裡可以引入global

def compare():
    global guess
    print("修改前的謎底:%s" % guess)
    times = 3
    while times > 0:
        value = float(input("請輸入你所猜數字, 你還有%s次機會" % times))
        if value == guess:
            return "恭喜,猜對啦"
        else:
            guess = 1
            times -= 1
    return "很遺憾,你的次數用完啦", "此時謎底為:%s" % guess


print(compare())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
修改前的謎底:-10
請輸入你所猜數字, 你還有3次機會64
請輸入你所猜數字, 你還有2次機會978
請輸入你所猜數字, 你還有1次機會3
('很遺憾,你的次數用完啦', '此時謎底為:1')

函式巢狀

函式巢狀是指函式裡面又存在函式,經典案例遞迴

def factorial_calculation():
    number = int(input("請輸入整數"))
    if number <= 0:
        return "請輸入大於0的正整數"

    def factorial(number):
        if number <= 1:
            return 1
        return number * factorial(number-1)
    return factorial(number)


print(factorial_calculation())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
請輸入整數6
720