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