python入门之函数调用第二关_猪行天下之Python基础——5.1 函数(上)
內(nèi)容簡(jiǎn)述:
1、函數(shù)定義
2、形參與實(shí)參
3、關(guān)鍵字參數(shù)與默認(rèn)參數(shù)
4、可變參數(shù)
5、全局變量與局部變量
6、內(nèi)部函數(shù)
7、閉包
8、lambda表達(dá)式
9、遞歸
1、函數(shù)定義
我們可以將一些實(shí)現(xiàn)特定功能,重復(fù)使用到的「代碼片段」抽取出來,封裝成一個(gè)函數(shù)。比如求兩個(gè)數(shù)和的函數(shù):
def?plus(a,?b):
"""
計(jì)算兩個(gè)數(shù)的和
:param?a:?第一個(gè)參數(shù)
:param?b:?第二個(gè)參數(shù)
:return:?兩個(gè)參數(shù)的和
"""
return?a?+?b
if?__name__?==?'__main__':
print("1?+?2?=?%d"?%?plus(1,?2))
復(fù)制代碼
運(yùn)行結(jié)果如下:
1?+?2?=?3
復(fù)制代碼
從上面的求和函數(shù)可以初窺函數(shù)定義的一些端倪,接著具體說下規(guī)則:
函數(shù)定義格式:def 函數(shù)名(傳入?yún)?shù))
使用 `return` 返回值,不寫的話默認(rèn)返回 None 值。
Python函數(shù)的 返回值可以有多個(gè) ,本質(zhì)上利用的元組。
Python傳遞的 參數(shù)有多個(gè) 的話,可以用逗號(hào)隔開。
一個(gè)建議:函數(shù)定義時(shí),可在函數(shù)的第一行語句中選擇性地使用文檔字符串編寫函數(shù)說明,除了方便閱讀,使用help(函數(shù)名)也可以拿到這個(gè)函數(shù)的說明信息。
2、形參與實(shí)參
定義函數(shù)時(shí),函數(shù)名后傳入的參數(shù)叫「形參」,調(diào)用函數(shù)時(shí),函數(shù)名后傳入的參數(shù)叫「實(shí)參」。這里還涉及到一個(gè)「?jìng)髦蹬c傳址」的問題,傳值就是傳入一個(gè)參數(shù)的值,而傳址則是傳入一個(gè)參數(shù)的內(nèi)存地址。兩者的區(qū)別是:如果函數(shù)是傳值類型的,在函數(shù)里修改了參數(shù)的值,外部的變量(實(shí)參)是不會(huì)改變的,比如下面這樣一段代碼:
def?f(a):
a?=?1
b?=?0
f(b)
print(b)
復(fù)制代碼
運(yùn)行結(jié)果如下:
0
復(fù)制代碼
盡管我們修改了傳入?yún)?shù)的值,但是實(shí)參卻依舊是0,沒有改變,這就是傳參,如果傳遞的是內(nèi)存地址,修改的了話實(shí)參也會(huì)受影響。但是Python和其他編程語言有點(diǎn)不同(比如C語言里可以用&參數(shù)名傳地址)。
Python不允許開發(fā)者選擇采用傳值還是傳址,而是采用「?jìng)鲗?duì)象引用」的方式,如果傳入的參數(shù)是一個(gè)不可變對(duì)象(數(shù)字,字符串和元組)的引用,就不能修改原始對(duì)象的值;如果傳入的參數(shù)是一個(gè)可變對(duì)象(列表,字典)的引用,就能直接修改原始對(duì)象的值。
比如下面這樣一串代碼:
def?f(a):
b[0]?=?1
b?=?[0]
f(b)
print(b)
復(fù)制代碼
運(yùn)行結(jié)果如下:
[1]
復(fù)制代碼
3、關(guān)鍵字參數(shù)與默認(rèn)參數(shù)
「關(guān)鍵字參數(shù)」:當(dāng)函數(shù)需要傳入的參數(shù)有多個(gè)的時(shí)候,怕參數(shù)混淆傳錯(cuò),可以在傳入的時(shí)候指定形參的參數(shù)名,比如:plus(a = 1, b = 2)。
「默認(rèn)參數(shù)」:在 定義形參的時(shí)候賦予初始值,調(diào)用的時(shí)候就可以不帶參數(shù)去調(diào)用函數(shù),比如:
def plus(a=1, b = 2),調(diào)用的時(shí)候直接plus()或者只傳入一個(gè)參數(shù)plus(3)都是可以的,還可以配合關(guān)鍵字參數(shù)指定傳入的是哪個(gè)參數(shù)。另外,默認(rèn)參數(shù)也稱作「缺省參數(shù)」。
4、可變參數(shù)
有時(shí)傳入函數(shù)中的 參數(shù)數(shù)目 可能是 不固定 的,比如,要你計(jì)算一堆數(shù)字的和,而具體有多少
個(gè)數(shù)字不知道,這個(gè)時(shí)候就可以使用可變參數(shù)了。只需要在函數(shù)定義時(shí)在參數(shù)前加上* 星號(hào),
就代表這個(gè)參數(shù)是可變參數(shù)(其實(shí)是只是把數(shù)據(jù)打包成了一個(gè)元組)。
另外,如果除了可變參數(shù)外還有其他的參數(shù),那么寫在可變參數(shù)后的參數(shù)要用關(guān)鍵字參數(shù)指定,
否則會(huì)加入可變參數(shù)的范疇。還有一點(diǎn)要注意,如果傳入的參數(shù)是列表或者元組,會(huì)被再次
打包成元組,如果想解包的話,需要在實(shí)參前加*,代碼示例如下:
def?plus(*a):
result?=?0
for?b?in?a:
print(b,?end='\t')
if?__name__?==?'__main__':
a?=?[1,?2,?3,?4,?5]
plus(a)
print()
plus(*a)
復(fù)制代碼
運(yùn)行結(jié)果如下:
[1,?2,?3,?4,?5]
1???2???3???4???5
復(fù)制代碼
另外,如果想把參數(shù)打包成字典的方式,可在函數(shù)形參前使用兩個(gè)**標(biāo)識(shí)。
5、全局變量與局部變量
全局變量:定義在最外部,可在函數(shù)內(nèi)部進(jìn)行訪問,但不能直接修改。
局部變量:定義在函數(shù)內(nèi)部,在函數(shù)外部無法訪問的參數(shù)和變量。
局部變量無法在外部訪問的原因:
Python在運(yùn)行函數(shù)時(shí),會(huì)利用棧(Stack)來存儲(chǔ)數(shù)據(jù),執(zhí)行完函數(shù)后,所有數(shù)據(jù)會(huì)被自動(dòng)刪除。
函數(shù)中無法修改全局變量的原因:
試圖在函數(shù)里修改全局變量的值時(shí),Python會(huì)自動(dòng)在函數(shù)內(nèi)部新建一個(gè)名字一樣的局部變量代替。如果硬是要修改,可以在函數(shù)內(nèi)部使用global關(guān)鍵字修飾全局變量,但是不建議這樣做,會(huì)使得程序維護(hù)成本的提高。
6、內(nèi)部函數(shù)
所謂的內(nèi)部函數(shù)其實(shí)就是「函數(shù)嵌套」,在一個(gè)函數(shù)中嵌套另一個(gè)函數(shù),要注意:
內(nèi)部函數(shù)的作用域,只在內(nèi)部函數(shù)的「直接外部函數(shù)內(nèi)」,外部是無法調(diào)用的沒,外部調(diào)用內(nèi)部函數(shù)會(huì)直接報(bào):函數(shù)找不到的錯(cuò)誤!
內(nèi)部函數(shù)無法直接修改外部函數(shù)中的變量,否則會(huì)報(bào)UnboundLocalError錯(cuò)誤!如果想在內(nèi)部函數(shù)中直接修改,可以把直接外部函數(shù)中的變量通過容器類型來存放,或者使用Python提供的 nonlocal關(guān)鍵字 修飾。代碼示例如下:
def?fun_x():
x?=?[10]
y?=?10
def?fun_y():
x[0]?+=?x[0]
nonlocal?y
y?*=?y
return?x[0]?*?y
return?fun_y()
if?__name__?==?'__main__':
print(fun_x())
復(fù)制代碼
運(yùn)行結(jié)果如下:
2000
復(fù)制代碼
7、閉包
在函數(shù)內(nèi)嵌套了另一個(gè)函數(shù),如果「內(nèi)部函數(shù)引用了外部函數(shù)的變量」,則可能產(chǎn)生閉包。
Python中形成閉包的三個(gè)條件:
函數(shù)嵌套
內(nèi)部函數(shù)引用外部變量
外部函數(shù)返回內(nèi)部函數(shù)
一個(gè)函數(shù)閉包的代碼示例如下:
def?outer(a):
b?=?1
def?inner():
print(a?+?b)
return?inner
if?__name__?==?'__main__':
test_1?=?outer(2)
test_1()
復(fù)制代碼
運(yùn)行結(jié)果如下:
2
復(fù)制代碼
在上面的代碼中,直接把內(nèi)部函數(shù)當(dāng)做返回值返回了,b是一個(gè)局部變量,按理來說,生命周期在調(diào)用完outer()函數(shù)后就完結(jié)了。但是載上面的代碼中,調(diào)用test_1時(shí),b變量的值卻正常輸出了,函數(shù)閉包使得函數(shù)的「局部變量信息」得以保存。
Python中通過__closure__屬性保存閉包中的局部變量,把上面test_1函數(shù)里的東東
打印出來,代碼如下:
print(test_1.__closure__)
print(test_1.__closure__[0].cell_contents)
print(test_1.__closure__[1].cell_contents)
復(fù)制代碼
運(yùn)行結(jié)果如下:
(,?)
2
1
復(fù)制代碼
8、lambda表達(dá)式
在Python中可以使用lambda關(guān)鍵字來創(chuàng)建匿名函數(shù),直接返回一個(gè)函數(shù)對(duì)象,而不用去糾結(jié)給函數(shù)起什么名字,省去了定義函數(shù)的步驟,從而簡(jiǎn)化代碼,一個(gè)對(duì)比大小簡(jiǎn)單的lambda表達(dá)式代碼示例如下:
big?=?lambda?x,?y:?x?>?y
print("第一個(gè)參數(shù)比第二個(gè)參數(shù)大:%s"?%?big(1,?2))
復(fù)制代碼
運(yùn)行結(jié)果如下:
第一個(gè)參數(shù)比第二個(gè)參數(shù)大:False
復(fù)制代碼
9、遞歸
所謂的遞歸就是「函數(shù)調(diào)用自身」,最簡(jiǎn)單的遞歸求和代碼示例如下:
def?sum(n):
if?n?==?1:
return?1
else:
return?n?+?sum(n?-?1)
print("1到100的求和結(jié)果是:?%d"?%?sum(100))
復(fù)制代碼
運(yùn)行結(jié)果如下:
1到100的求和結(jié)果是:?5050
復(fù)制代碼
另外要注意兩點(diǎn):
遞歸要有結(jié)束條件,以避免遞歸的無休止調(diào)用!
遞歸可以簡(jiǎn)化程序,但不一定能提高程序的執(zhí)行效率!
如果本文對(duì)你有所幫助,歡迎
留言,點(diǎn)贊,轉(zhuǎn)發(fā)
素質(zhì)三連,謝謝😘~
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的python入门之函数调用第二关_猪行天下之Python基础——5.1 函数(上)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql建表的auto_increme
- 下一篇: 关于MySQL数据库游标的笔试题_关于B