Python學(xué)習(xí)之函數(shù)的定義與使用詳解
函數(shù)的定義
什么是函數(shù)? — > 函數(shù)是具有某種特定功能的代碼塊,可以重復(fù)使用(在前面數(shù)據(jù)類型相關(guān)章節(jié),其實(shí)已經(jīng)出現(xiàn)了很多 Python 內(nèi)置函數(shù)了)。它使得我們的程序更加模塊化,不需要編寫大量重復(fù)的代碼。
函數(shù)可以提前保存起來(lái),并給它起一個(gè)獨(dú)一無(wú)二的名字,只要知道它的名字就能使用這段代碼。函數(shù)還可以接收數(shù)據(jù),并根據(jù)數(shù)據(jù)的不同做出不同的操作,最后再把處理結(jié)果反饋給我們。
由此我們得知:
- 將一件事情的步驟封裝在一起并得到最終結(jié)果的步驟,就是函數(shù)的過(guò)程。
- 函數(shù)名代表了該函數(shù)要做的事情。
- 函數(shù)體是實(shí)現(xiàn)函數(shù)功能的流程。
- 在實(shí)際工作中,我們把實(shí)現(xiàn)一個(gè)函數(shù)也叫做 “實(shí)現(xiàn)一個(gè)方法或者實(shí)現(xiàn)一個(gè)功能”
- 函數(shù)可以幫助我們重復(fù)使用功能,通過(guò)函數(shù)名我們也可以知道函數(shù)的作用。
函數(shù)的分類
內(nèi)置函數(shù):在前面數(shù)據(jù)類型相關(guān)章節(jié),其實(shí)已經(jīng)出現(xiàn)了很多 Python 內(nèi)置函數(shù)了。如 input、id、type、max、min、int、str等 ,這些都是 Python 的內(nèi)置函數(shù)。也就是 Python 已經(jīng)為我們定義好的函數(shù),我們直接拿來(lái)使用即可。
自定義函數(shù):由于每個(gè)業(yè)務(wù)的不同,需求也各不相同。Python無(wú)法提供給我們所有我們想要的功能,這時(shí)候我們就需要去開發(fā),實(shí)現(xiàn)我們自己想要的功能。這部分函數(shù),我們叫它 自定義函數(shù) 。
無(wú)論是內(nèi)置函數(shù),還是自定義函數(shù),他們的書寫方法都是一樣的。
函數(shù)的創(chuàng)建方法 - def
def 關(guān)鍵字的功能:實(shí)現(xiàn) Python 函數(shù)的創(chuàng)建。
def 關(guān)鍵字定義函數(shù):定義函數(shù),也就是創(chuàng)建一個(gè)函數(shù),可以理解為創(chuàng)建一個(gè)具有某些用途的工具。定義函數(shù)需要用 def 關(guān)鍵字實(shí)現(xiàn),具體的語(yǔ)法格式如下:
def 函數(shù)名(參數(shù)列表):
todo something # 實(shí)現(xiàn)特定功能的多行代碼
[return [返回值]] # 用 [] 括起來(lái)的為可選擇部分,即可以使用,也可以省略。
# >>> 各部分參數(shù)的含義如下:
# >>> 函數(shù)名:其實(shí)就是一個(gè)符合 Python 語(yǔ)法的標(biāo)識(shí)符,但不建議使用 a、b、c 這類簡(jiǎn)單的標(biāo)識(shí)符作為函數(shù)名,函數(shù)名最好能夠體現(xiàn)出該函數(shù)的功能(如user_info, user_mobile)。
# >>> 參數(shù)列表:設(shè)置該函數(shù)可以接收多少個(gè)參數(shù),多個(gè)參數(shù)之間用逗號(hào)( , )分隔。
# >>> [return [返回值] ]:整體作為函數(shù)的可選參參數(shù),用于設(shè)置該函數(shù)的返回值。也就是說(shuō),一個(gè)函數(shù),可以用返回值,也可以沒有返回值,是否需要根據(jù)實(shí)際情況而定。
注意,在創(chuàng)建函數(shù)時(shí),即使函數(shù)不需要參數(shù),也必須保留一對(duì)空的 “()” ,否則 Python 解釋器將提示“invaild syntax”錯(cuò)誤。另外,如果想定義一個(gè)沒有任何功能的空函數(shù),可以使用 pass 語(yǔ)句作為占位符。
示例如下:
def user_name():
print('這是一個(gè) \'user_name\'函數(shù) ')
user_name()
# >>> 執(zhí)行結(jié)果如下
# >>> 這是一個(gè) 'user_name'函數(shù)
函數(shù)的返回值 - return
return 的意思就是返回的意思,它是將函數(shù)的結(jié)果返回的關(guān)鍵字,所以函數(shù)的返回值也是通過(guò) return 來(lái)實(shí)現(xiàn)的。
需要注意的是,return 只能在函數(shù)體內(nèi)使用; return 支持返回所有的數(shù)據(jù)類型,當(dāng)一個(gè)函數(shù)返回之后,我們可以給這個(gè)返回值賦予一個(gè)新的變量來(lái)使用。
由此我們總結(jié)出:
- return 是將函數(shù)結(jié)果返回的關(guān)鍵字
- return 只能在函數(shù)體內(nèi)使用
- return 支持返回所有的數(shù)據(jù)類型
- 有返回值的函數(shù),可以直接賦值給一個(gè)變量
return 的用法,示例如下:
def add(a,b):
c = a + b
return c
#函數(shù)賦值給變量
result = add(a=1,b=1)
print(result)
#函數(shù)返回值作為其他函數(shù)的實(shí)際參數(shù)
print(add(3,4))
需要注意的是,return 語(yǔ)句在同一函數(shù)中可以出現(xiàn)多次,但只要有一個(gè)得到執(zhí)行,就會(huì)直接結(jié)束函數(shù)的執(zhí)行。
現(xiàn)在我們利用 return 關(guān)鍵字 ,嘗試自定義一個(gè) capitalize 函數(shù)。示例如下:
def capitalize(data):
index = 0
temp = ''
for item in data:
if index == 0:
temp = item.upper()
else:
temp += item
index += 1
return temp
result = capitalize('hello , Jack')
print(result)
# >>> 執(zhí)行結(jié)果如下
# >>> Hello , Jack

再一次注意到,只要有一個(gè)得到執(zhí)行,就會(huì)直接結(jié)束函數(shù)的執(zhí)行。
return 與 print 的區(qū)別
print 只是單純的將對(duì)象打印輸出,并不支持賦值語(yǔ)句。
return 是對(duì)函數(shù)執(zhí)行結(jié)果的返回,且支持賦值語(yǔ)句;但是我們可以將含有 renturn 值的函數(shù)放在 print 里進(jìn)行打印。
函數(shù)的傳參
必傳參數(shù):平時(shí)最常用的,必傳確定數(shù)量的參數(shù)
默認(rèn)參數(shù):在調(diào)用函數(shù)時(shí)可以傳也可以不傳,如果不傳將使用默認(rèn)值
不確定參數(shù):可變長(zhǎng)度參數(shù)(也叫可變參數(shù))
關(guān)鍵字參數(shù):長(zhǎng)度可變,但是需要以 key-value 形式傳參
必傳參數(shù)
什么是必傳參數(shù)? —> 在定義函數(shù)的時(shí)候,沒有默認(rèn)值且必須在函數(shù)執(zhí)行的時(shí)候傳遞進(jìn)去的參數(shù);且順序與參數(shù)順序相同,這就是必傳參數(shù)。
- 函數(shù)中定義的參數(shù)沒有默認(rèn)值,在調(diào)用函數(shù)的時(shí)候,如果不傳入?yún)?shù),則會(huì)報(bào)錯(cuò)。
- 在定義函數(shù)的時(shí)候,參數(shù)后邊沒有等號(hào)與默認(rèn)值。
- 錯(cuò)誤的函數(shù)傳參方式:def add(a=1, b=1)
錯(cuò)誤示例如下:
def add(a, b):
return a + b
result = add()
print(result)
# >>> 執(zhí)行結(jié)果如下
# >>> TypeError: add() missing 2 required positional arguments: 'a' and 'b'
正確的示例如下:
def add(a, b):
return a + b
result = add(1, 2)
print(result)
# >>> 執(zhí)行結(jié)果如下
# >>> 3
# >>> add 函數(shù)有兩個(gè)參數(shù),第一個(gè)參數(shù)是 a,第二個(gè)參數(shù)是 b
# >>> 傳入的兩個(gè)整數(shù)按照位置順序依次賦給函數(shù)的參數(shù) a 和 b,參數(shù) a 和參數(shù) b 被稱為位置參數(shù)
傳遞的參數(shù)個(gè)數(shù)必須等于參數(shù)列表的數(shù)量
根據(jù)函數(shù)定義的參數(shù)位置來(lái)傳遞參數(shù),要求傳遞的參數(shù)與函數(shù)定義的參數(shù)兩者一一對(duì)應(yīng)
如果 “傳遞的參數(shù)個(gè)數(shù)” 不等于 “函數(shù)定義的參數(shù)個(gè)數(shù)”,運(yùn)行時(shí)會(huì)報(bào)錯(cuò)
錯(cuò)誤傳參數(shù)量示例如下:
def add(a, b):
return a + b
sum = add(1, 2, 3)
# >>> 執(zhí)行結(jié)果如下
# >>> sum = add(1, 2, 3)
# >>> TypeError: add() takes 2 positional arguments but 3 were given
默認(rèn)參數(shù)
在定義函數(shù)的時(shí)候,定義的參數(shù)含有默認(rèn)值,通過(guò)賦值語(yǔ)句給參數(shù)一個(gè)默認(rèn)的值。
使用默認(rèn)參數(shù),可以簡(jiǎn)化函數(shù)的調(diào)用,尤其是在函數(shù)需要被頻繁調(diào)用的情況下
如果默認(rèn)參數(shù)在調(diào)用函數(shù)的時(shí)候被給予了新的值,函數(shù)將優(yōu)先使用新傳入的值進(jìn)行工作
示例如下:
def add(a, b, c=3):
return a + b + c
result = add(1, 2) # 1 對(duì)應(yīng)的 a ;2 對(duì)應(yīng)的 b ; 沒有傳入 C 的值,使用 C 的默認(rèn)值 3。
print(result)
# >>> 執(zhí)行結(jié)果如下
# >>> 6
def add(a, b, c=3):
return a + b + c
result = add(1, 2, 7) # 1 對(duì)應(yīng)的 a ;2 對(duì)應(yīng)的 b ; 傳入 C 的值為 7,未使用 C 的默認(rèn)值 3。
print(result)
# >>> 執(zhí)行結(jié)果如下
# >>> 10
不確定參數(shù)(可變參數(shù))
這種參數(shù)沒有固定的參數(shù)名和數(shù)量(不知道要傳的參數(shù)名具體是什么)
不確定參數(shù)格式如下:
def add(*args, **kwargs):
pass
# *args :將無(wú)參數(shù)的值合并成元組
# **kwargs :將有參數(shù)與默認(rèn)值的賦值語(yǔ)句合并成字典
*args 代表:將無(wú)參數(shù)的值合并成元組
**kwargs 代表:將有參數(shù)與默認(rèn)值的賦值語(yǔ)句合并成字典
從定義與概念上似乎難以理解,現(xiàn)在我們通過(guò)示例來(lái)看一下:
def test_args(*args, **kwargs):
print(args, type(args))
print(kwargs, type(kwargs))
test_args(1, 2, 3, name='Neo', age=18)
# >>> 執(zhí)行結(jié)果如下
# >>> (1, 2, 3) <class 'tuple'>
# >>> {'name': 'Neo', 'age': 18} <class 'dict'>
# >>> args 將輸入的參數(shù)轉(zhuǎn)成了一個(gè)元組
# >>> kwargs 將輸入的賦值語(yǔ)句轉(zhuǎn)成了一個(gè)字典
# >>> 在使用的時(shí)候,我們還可以根據(jù)元組與字典的特性,對(duì)這些參數(shù)進(jìn)行使用;示例如下:
def test_args(*args, **kwargs):
if len(args) >= 1:
print(args[2])
if 'name' in kwargs:
print(kwargs['name'])
test_args(1, 2, 3, name='Neo', age=18)
# >>> 執(zhí)行結(jié)果如下
# >>> 3 根據(jù)元組特性,打印輸出 args 索引為 2 的值
# >>> Neo 根據(jù)字典特性,打印輸出 kwargs 的 key 為 name 的 value
def test_args(*args, **kwargs):
if len(args) >= 1:
print(args[2])
else:
print('當(dāng)前 args 的長(zhǎng)度小于1')
if 'name' in kwargs:
print(kwargs['name'])
else:
print('當(dāng)前 kwargs 沒有 key為 name 的元素')
test_args(1, 2, 3, name1='Neo', age=18)
# >>> 執(zhí)行結(jié)果如下
# >>> 3 根據(jù)元組特性,打印輸出 args 索引為 2 的值3
# >>> 當(dāng)前 kwargs 沒有 key為 name 的元素(傳入的 kwargs 為 name1='Neo', age=18;沒有 name)
參數(shù)規(guī)則
def add(a, b=1, *args, **kwargs)
參數(shù)的定義從左到右依次是 a - 必傳參數(shù) 、b - 默認(rèn)參數(shù) 、可變的 *args 參數(shù) 、可變的 **kwargs 參數(shù)
函數(shù)的參數(shù)傳遞非常有靈活性
必傳參數(shù)與默認(rèn)參數(shù)的傳參也非常具有多樣化
示例如下:
def add(a, b=2):
print(a + b)
# 我們來(lái)看一下該函數(shù)可以通過(guò)哪些方式傳遞參數(shù)來(lái)執(zhí)行
add(1, 2) # 執(zhí)行結(jié)果為 : 3
add(1) # 執(zhí)行結(jié)果為 : 3
add(a=1, b=2) # 執(zhí)行結(jié)果為 : 3
add(a=1) # 執(zhí)行結(jié)果為 : 3
add(b=2, a=1) # 執(zhí)行結(jié)果為 : 3
add(b=2)
# 執(zhí)行結(jié)果為 : TypeError: add() missing 1 required positional argument: 'a' 。
# (因?yàn)?a 是必傳參數(shù),這里只傳入 b 的參數(shù)是不行的)
def test(a, b, *args):
print(a, b, args)
int_tuple = (1, 2)
test(1, 2, *int_tuple)
# >>> 執(zhí)行結(jié)果如下
# >>> 1 2 (1, 2)
# ***********************************************************
def test(a, b, *args):
print(a, b, args)
int_tuple = (1, 2)
test(a=1, b=2, *int_tuple)
# >>> 執(zhí)行結(jié)果如下
# >>> TypeError: test() got multiple values for argument 'a'
# >>> 提示我們參數(shù)重復(fù),這是因?yàn)?必傳參數(shù)、默認(rèn)參數(shù)、可變參數(shù)在一起時(shí)。如果需要賦值進(jìn)行傳參,需要將可變參數(shù)放在第一位,然后才是 必傳參數(shù)、默認(rèn)參數(shù)。(這是一個(gè)特例)
# ************************************************************
def test(*args, a, b):
print(a, b, args)
int_tuple = (1, 2)
test(a=1, b=2, *int_tuple)
# >>> 執(zhí)行結(jié)果如下
# >>> 1 2 (1, 2)
# >>> 這種改變 必傳參數(shù)、默認(rèn)參數(shù)、可變參數(shù) 的方式,一般我們是不推薦使用的
def test(a, b=1, **kwargs):
print(a, b, kwargs)
test(1, 2, name='Neo')
test(a=1, b=2, name='Jack')
test(name='Jack', age=18, a=1, b=2)
# >>> 執(zhí)行結(jié)果如下
# >>> 1 2 {'name': 'Neo'}
# >>> 1 2 {'name': 'Jack'}
# >>> 1 2 {'name': 'Jack', 'age': 18}
注意:如果傳參的順序發(fā)生變化,一定要使用賦值語(yǔ)句進(jìn)行傳參。
函數(shù)小練習(xí)
需求:定義一個(gè) login 函數(shù),向函數(shù)內(nèi)傳入形參 username,password,當(dāng) username 值為 admin 且password值為字符串 123456 時(shí),返回“登錄成功”;否則返回“請(qǐng)重新登錄”
def login(username, password):
# 定義一個(gè)登錄函數(shù),傳入 username, password 必填參數(shù)
if username == "admin" and password == "123456":
# 使用if語(yǔ)句,判斷用戶名和密碼為“admin”和“123456”
print("登錄成功") # 返回登錄成功
else:
# 使用else子句處理用戶名和密碼非“admin”和“123456”的情況
print("請(qǐng)重新登錄") # 返回請(qǐng)重新登錄
# 調(diào)用函數(shù),向函數(shù)內(nèi)傳入'admin','123456'和'test','123456'兩組數(shù)據(jù)測(cè)試結(jié)果
login(username="admin", password="123456") # 打印函數(shù)測(cè)試結(jié)果
login(username="test", password="123456") # 打印函數(shù)測(cè)試結(jié)果
函數(shù)的參數(shù)類型定義
前文我們學(xué)習(xí)了函數(shù)的定義方法與使用方法,在定義參數(shù)的時(shí)候我們并不知道參數(shù)對(duì)應(yīng)的數(shù)據(jù)類型是什么。都是通過(guò)函數(shù)體內(nèi)根據(jù)業(yè)務(wù)調(diào)用場(chǎng)景去判斷的,如果傳入的類型與也無(wú)償性不符,就會(huì)產(chǎn)生報(bào)錯(cuò)?,F(xiàn)在我們學(xué)習(xí)一種方法,可以在定義函數(shù)的時(shí)候,將參數(shù)類型與參數(shù)一同定義,方便我們知道每一個(gè)參數(shù)需要傳入的數(shù)據(jù)類型。
我們來(lái)看一個(gè)例子:
def person(name:str, age:int=18):
print(name, age)
- 必傳參數(shù):參數(shù)名 + 冒號(hào) + 數(shù)據(jù)類型函數(shù) ,為聲明必傳參數(shù)的數(shù)據(jù)類型
- 默認(rèn)參數(shù):參數(shù)名 + 冒號(hào) + 數(shù)據(jù)類型函數(shù) + 等號(hào) + 默認(rèn)值,為聲明默認(rèn)參數(shù)的數(shù)據(jù)類型
- 需要注意的是,對(duì)函數(shù)的定義數(shù)據(jù)類型在 python 3.7 之后的版本才有這個(gè)功能
- 雖然我們給函數(shù)參數(shù)定義了數(shù)據(jù)類型,但是在函數(shù)執(zhí)行的時(shí)候仍然不會(huì)對(duì)參數(shù)類型進(jìn)行校驗(yàn),依然是通過(guò)函數(shù)體內(nèi)根據(jù)業(yè)務(wù)調(diào)用場(chǎng)景去判斷的。這個(gè)定義方法只是單純的肉眼上的查看。
示例如下:
def add(a: int, b: int = 3):
print(a + b)
add(1, 2)
add('Hello', 'World')
# >>> 執(zhí)行結(jié)果如下:
# >>> 3
# >>> HelloWorld
def add(a: int, b: int = 3, *args:int, **kwargs:str):
print(a, b, args, kwargs)
add(1, 2, 3, '4', name='Neo')
# >>> 執(zhí)行結(jié)果如下:
# >>> 1 2 (3, '4') {'name': 'Neo'}
我們發(fā)現(xiàn)執(zhí)行的函數(shù)并沒有報(bào)錯(cuò),add(‘Hello’, ‘World’) 也通過(guò)累加的方式拼接在了一起
所以說(shuō),雖然我們定義了 int 類型,但是并沒有做校驗(yàn),只是單純的通過(guò)肉眼告知我們參數(shù)是 int 類型,后續(xù)我們進(jìn)入python高級(jí)進(jìn)階階段可以自己編寫代碼進(jìn)行校驗(yàn)。
全局變量與局部變量
全局變量:在當(dāng)前 py 文件都生效的變量
- 在 python 腳本最上層代碼塊的變量
- 全局變量可以在函數(shù)內(nèi)被讀取使用
局部變量:在函數(shù)內(nèi)部,類內(nèi)部,lamda.的變量,它的作用域僅在函數(shù)、類、lamda 里面
- 在函數(shù)體內(nèi)定義的變量
- 局部變量無(wú)法在自身函數(shù)以外使用
全局變量
示例如下:
# coding:utf-8
name = 'Neo'
age = 18
def test01():
print(name)
def test02():
print(age)
def test03():
print(name, age)
test01()
test02()
test03()
# >>> 執(zhí)行結(jié)果如下:
# >>> Neo
# >>> 18
# >>> Neo 18
# >>> 這里我們可以看到聲明的 全局變量 在多個(gè)函數(shù)體內(nèi)都可以被使用
局部變量
示例如下:
# coding:utf-8
name = 'Neo'
age = 18
def test01():
name = 'Jack'
age = 17
print('這是函數(shù)體內(nèi)的局部變量', name, age)
test01()
print('這是函數(shù)體外的全局變量', name, age)
# >>> 執(zhí)行結(jié)果如下:
# >>> 這是函數(shù)體內(nèi)的局部變量 Jack 17
# >>> 這是函數(shù)體外的全局變量 Neo 18
# >>> 這里我們既聲明聲明了全局變量,同時(shí)還在函數(shù)體內(nèi)變更了變量的值使其成為了局部變量。
# >>> 同時(shí),根據(jù)打印輸出的結(jié)果我們可以看出局部變量?jī)H僅作用于函數(shù)體內(nèi)。
全局變量 在 函數(shù)體內(nèi)真的就不能被修改么?當(dāng)然是可以的,借助關(guān)鍵字 global 就可以實(shí)現(xiàn)。
global 關(guān)鍵字
global 關(guān)鍵字的功能:將全局變量可以在函數(shù)體內(nèi)進(jìn)行修改
global 關(guān)鍵字的用法:示例如下
# coding:utf-8
name = 'Neo'
def test():
global name
name = 'Jack'
print('函數(shù)體內(nèi) \'name\' 的值為:', name)
print('函數(shù)體外 \'name\' 的值為:', name)
# >>> 執(zhí)行結(jié)果如下:
# >>> 函數(shù)體內(nèi) 'name' 的值為: Jack
# >>> 函數(shù)體外 'name' 的值為: Jack
注意:日常開發(fā)工作中,不建議使用 global 對(duì) 全局變量進(jìn)行修改
再來(lái)看一個(gè)案例:
test_dict = {'name': 'Neo', 'age': '18'}
def test():
test_dict['sex'] = 'man'
test_dict.pop('age')
print('函數(shù)體內(nèi) \'test_dict\' 的值為:', test_dict)
test()
print('函數(shù)體外 \'test_dict\' 的值為:', test_dict)
# >>> 執(zhí)行結(jié)果如下:
# >>> 函數(shù)體內(nèi) 'test_dict' 的值為: {'name': 'Neo', 'sex': 'man'}
# >>> 函數(shù)體外 'test_dict' 的值為: {'name': 'Neo', 'sex': 'man'}
前面我們是通過(guò) global 關(guān)鍵字修改了函數(shù)體內(nèi)的變量的值,為什么在這里沒有使用 global 關(guān)鍵字,在函數(shù)體內(nèi)修改了 test_dict 的值卻影響到了函數(shù)體外的變量值呢?
其實(shí),通過(guò) global 關(guān)鍵字修改的全局變量?jī)H支持?jǐn)?shù)字、字符串、空類型、布爾類型,如果在局部變量想要使用全局變量的字典、列表類型,是不需要通過(guò) global 關(guān)鍵字指引的。
遞歸函數(shù)
什么是遞歸函數(shù)? —> 通俗的來(lái)說(shuō),一個(gè)函數(shù)不停的將自己反復(fù)執(zhí)行,這就是遞歸函數(shù)。(通常是由于函數(shù)對(duì)自己的執(zhí)行結(jié)果不滿意,才需要這樣反復(fù)的執(zhí)行。)
遞歸函數(shù)的定義方法
示例如下:
def test(a):
print(a)
return test(a) # 通過(guò)返回值,直接執(zhí)行自身的函數(shù)
test(1)
# >>> 執(zhí)行結(jié)果如下:
# >>> 1
# >>> 1.... 會(huì)一直執(zhí)行下去,有可能會(huì)造成死機(jī),不要嘗試。
count = 0
def test():
global count
count += 1
if count != 5:
print('\'count\'的條件不滿足,需要重新執(zhí)行。當(dāng)前\'count\'的值為%s' % count)
return test()
else:
print('當(dāng)前\'count\'的值為%s' % count)
test()
# >>> 執(zhí)行結(jié)果如下:
# >>> 'count'的條件不滿足,需要重新執(zhí)行。當(dāng)前'count'的值為1
# >>> 'count'的條件不滿足,需要重新執(zhí)行。當(dāng)前'count'的值為2
# >>> 'count'的條件不滿足,需要重新執(zhí)行。當(dāng)前'count'的值為3
# >>> 'count'的條件不滿足,需要重新執(zhí)行。當(dāng)前'count'的值為4
# >>> 當(dāng)前'count'的值為5
遞歸函數(shù)的說(shuō)明
首先我們要知道 遞歸函數(shù) 會(huì)造成的影響,遞歸函數(shù) 是不停的重復(fù)調(diào)用自身函數(shù)行程一個(gè)無(wú)限循環(huán),就會(huì)造成內(nèi)存溢出的情況,我們的電腦可能就要死機(jī)了。
遞歸函數(shù)雖然方便了我們用一段短小精悍的代碼便描述了一個(gè)復(fù)雜的算法(處理過(guò)程),但一定要謹(jǐn)慎使用。(使用循環(huán)來(lái)處理,不失為一個(gè)穩(wěn)妥的方案。)
所以我們要盡量的避免使用 遞歸函數(shù) ,如果真的要使用遞歸,一定要給予退出遞歸的方案。
lambda - 匿名函數(shù)
lambda 函數(shù)的功能:定義一個(gè)輕量化的函數(shù);所謂輕量化就是即用即刪除,很適合需要完成一項(xiàng)功能,但是此功能只在此一處使用。也就是說(shuō)不會(huì)重復(fù)使用的函數(shù),并且業(yè)務(wù)簡(jiǎn)單的場(chǎng)景,我們就可以通過(guò) lambda 來(lái)定義函數(shù)
lambda 函數(shù)的用法示例如下
# 定義匿名函數(shù)的兩種方法 # 方法1:無(wú)參數(shù)的匿名函數(shù) test = lambda: value # lambda + 冒號(hào) + value 值 , 賦值給一個(gè)變量 test() # 變量名 + 小括號(hào) ,至此 lambda 匿名函數(shù)就定義完了。(value實(shí)際上是具有 return 效果的) # 方法2:有參數(shù)的匿名函數(shù) test = lambda value,value:value*value # lambda + 兩個(gè)參數(shù) + 冒號(hào) + 兩個(gè)value簡(jiǎn)單的處理 , 賦值給一個(gè)變量 test(3, 5)
# 無(wú)參數(shù)的匿名函數(shù) test = lambda:1 result = test() print(result) # >>> 執(zhí)行結(jié)果如下: # >>> 1 # ********************* # 有參數(shù)的匿名函數(shù) test = lambda a, b: a+b result = test(1, 3) print(result) # >>> 執(zhí)行結(jié)果如下: # >>> 4 # ********************* test = lambda a, b: a>b result = test(1, 3) print(result) # >>> 執(zhí)行結(jié)果如下: # >>> False
再來(lái)看一個(gè)示例,加深對(duì) lambda 匿名函數(shù)的理解
users = [{'name': 'Neo'}, {'name': 'Jack'}, {'name': 'Lily'}]
users.sort(key=lambda user_sort: user_sort['name'])
print(users)
# >>> 執(zhí)行結(jié)果如下:
# >>> [{'name': 'Jack'}, {'name': 'Lily'}, {'name': 'Neo'}]
# >>> 我們看到 {'name': 'Jack'} 被排到了最前面,通過(guò) lambda 將列表中的每個(gè)成員作為參數(shù)傳入,
# >>> 并將元素中指定 key 為 name 的 value 作為了排序?qū)ο筮M(jìn)行排序。
關(guān)于 lambda 的簡(jiǎn)單使用,就介紹到這里。后續(xù)高級(jí)語(yǔ)法進(jìn)階章節(jié)會(huì)對(duì) lambda 匿名函數(shù) 的高級(jí)用法進(jìn)行詳細(xì)的講解。
函數(shù)練習(xí)
利用函數(shù)實(shí)現(xiàn)學(xué)生信息庫(kù)
現(xiàn)在我們學(xué)習(xí)完了 函數(shù)的基本知識(shí) ,接下來(lái)我們進(jìn)行一個(gè)總結(jié)和聯(lián)系。練習(xí)一個(gè)學(xué)生信息庫(kù)的案例,并且隨著之后的章節(jié)學(xué)習(xí)我們還會(huì)不端升級(jí)、優(yōu)化這個(gè)信息庫(kù),達(dá)到真正可以使用的功能。
接下來(lái)我們先定義出學(xué)生信息庫(kù)的基本結(jié)構(gòu),之后開發(fā)這個(gè)信息庫(kù)的增、刪、改、查功能。
# coding:utf-8
"""
@Author:Neo
@Date:2020/1/14
@Filename:students_info.py
@Software:Pycharm
"""
students = { # 定義一個(gè)學(xué)生字典,key 為 id,value 為 學(xué)生信息(name、age、class_number、sex)
1: {
'name': 'Neo',
'age': 18,
'class_number': 'A',
'sex': 'boy'
},
2: {
'name': 'Jack',
'age': 16,
'class_number': 'B',
'sex': 'boy'
},
3: {
'name': 'Lily',
'age': 18,
'class_number': 'A',
'sex': 'girl'
},
4: {
'name': 'Adem',
'age': 18,
'class_number': 'C',
'sex': 'boy'
},
5: {
'name': 'HanMeiMei',
'age': 18,
'class_number': 'B',
'sex': 'girl'
}
}
def check_user_info(**kwargs): # 定義一個(gè) check_user_info 函數(shù),檢查學(xué)生信息傳入食肉缺失
if 'name' not in kwargs:
return '沒有發(fā)現(xiàn)學(xué)生姓名'
if 'age' not in kwargs:
return '缺少學(xué)生年齡'
if 'sex' not in kwargs:
return '缺少學(xué)生性別'
if 'class_number' not in kwargs:
return '缺少學(xué)生班級(jí)'
return True
def get_all_students(): # 定義一個(gè) get_all_students 函數(shù),獲取所有學(xué)生信息并返回
for id_, value in students.items():
print('學(xué)號(hào):{}, 姓名:{}, 年齡:{}, 性別:{}, 班級(jí):{}'.format(
id_, value['name'], value['age'], value['sex'], value['class_number']
))
return students
def add_student(**kwargs): # 定義一個(gè) add_student 函數(shù),執(zhí)行添加學(xué)生信息的操作并進(jìn)行校驗(yàn),學(xué)生id 遞增
check = check_user_info(**kwargs)
if check != True:
print(check)
return
id_ = max(students) + 1
students[id_] = {
'name': kwargs['name'],
'age': kwargs['age'],
'sex': kwargs['sex'],
'class_number': kwargs['class_number']
}
def delete_student(student_id): # 定義一個(gè) delete_student 函數(shù),執(zhí)行刪除學(xué)生信息操作,并進(jìn)行是否存在判斷
if student_id not in students:
print('{} 并不存在'.format(student_id))
else:
user_info = students.pop(student_id)
print('學(xué)號(hào)是{}, {}同學(xué)的信息已經(jīng)被刪除了'.format(student_id, user_info['name']))
def update_student(student_id, **kwargs): # 定義一個(gè) update_student 函數(shù),執(zhí)行更新學(xué)生信息操作,并進(jìn)行校驗(yàn)
if student_id not in students:
print('并不存在這個(gè)學(xué)號(hào):{}'.format(student_id))
check = check_user_info(**kwargs)
if check != True:
print(check)
return
students[student_id] = kwargs
print('同學(xué)信息更新完畢')
# update_student(1, name='Atom', age=16, class_number='A', sex='boy') # 執(zhí)行 更新學(xué)生信息函數(shù),并查看結(jié)果
# get_all_students()
def get_user_by_id(student_id): # 定義一個(gè) get_user_by_id 函數(shù),可以通過(guò)學(xué)生 id 查詢學(xué)生信息
return students.get(student_id)
# print(get_user_by_id(3))
def search_users(**kwargs): # 定義一個(gè) search_users 函數(shù),可以通過(guò) 學(xué)生關(guān)鍵信息進(jìn)行模糊查詢
values = list(students.values())
key = None
value = None
result = []
if 'name' in kwargs:
key = 'name'
value = kwargs[key]
elif 'sex' in kwargs:
key = 'sex'
value = kwargs['sex']
elif 'class_number' in kwargs:
key = 'class_number'
value = kwargs[key]
elif 'age' in kwargs:
key = 'age'
value = kwargs[key]
else:
print('沒有發(fā)現(xiàn)搜索的關(guān)鍵字')
return
for user in values:
if user[key] == value:
result.append(user)
return result
users = search_users(sex='girl')
print(users)
# >>> 執(zhí)行結(jié)果如下:
# >>> [{'name': 'Lily', 'age': 18, 'class_number': 'A', 'sex': 'girl'}, {'name': 'HanMeiMei', 'age': 18, 'class_number': 'B', 'sex': 'girl'}]
以上就是Python學(xué)習(xí)之函數(shù)的定義與使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Python函數(shù)定義 使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python中tkinter庫(kù)的簡(jiǎn)單使用
這篇文章主要介紹了Python中tkinter庫(kù)的簡(jiǎn)單使用,Tkinter是Python中常用的GUI庫(kù),它使用Tk GUI工具包,并提供了創(chuàng)建各種GUI應(yīng)用程序的功能,需要的朋友可以參考下2023-10-10
python2.7實(shí)現(xiàn)爬蟲網(wǎng)頁(yè)數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了python2.7實(shí)現(xiàn)爬蟲網(wǎng)頁(yè)數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
使用Pandas實(shí)現(xiàn)可視化帶有標(biāo)簽列的數(shù)據(jù)表
Pandas是Python中一個(gè)靈活強(qiáng)大的數(shù)據(jù)處理庫(kù),它提供了大量數(shù)據(jù)操作和分析工具,本文我們將討論如何使用Pandas可視化帶有標(biāo)簽列的數(shù)據(jù)表,以便更好地呈現(xiàn)和傳達(dá)數(shù)據(jù)的信息,需要的可以了解下2024-02-02
Python?PEP8?代碼規(guī)范常見問(wèn)題及解決方法
最近換成?PyCharm?寫代碼總是會(huì)出現(xiàn)波浪號(hào),這才了解到?Python?的?PEP8?代碼規(guī)范,所以將常見的?PEP8?代碼規(guī)范問(wèn)題和解決方法記錄一下,養(yǎng)成良好的習(xí)慣,編寫規(guī)范的代碼2023-09-09
如何使用Python處理HDF格式數(shù)據(jù)及可視化問(wèn)題
這篇文章主要介紹了如何使用Python處理HDF格式數(shù)據(jù)及可視化問(wèn)題,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
Python繪圖示例程序中的幾個(gè)語(yǔ)法糖果你知道嗎
這篇文章主要為大家詳細(xì)介紹了Python繪圖示例程序中的幾個(gè)語(yǔ)法糖果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02
對(duì)python requests的content和text方法的區(qū)別詳解
今天小編就為大家分享一篇對(duì)python requests的content和text方法的區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10
python實(shí)現(xiàn)連續(xù)變量最優(yōu)分箱詳解--CART算法
今天小編就為大家分享一篇python實(shí)現(xiàn)連續(xù)變量最優(yōu)分箱詳解--CART算法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11

