這篇筆記記錄的知識(shí)點(diǎn):
- 函數(shù)的基本概念
- 自定義函數(shù)
- 函數(shù)的幾種參數(shù)
編程的三種方式:
1.OOP 面向?qū)ο缶幊?,萬(wàn)物皆對(duì)象,以class為主,抽象化
2.POP 面向過(guò)程編程,萬(wàn)事皆過(guò)程,def定義過(guò)程
3.函數(shù)式編程,將某種功能封裝起來(lái),用的時(shí)候直接調(diào)用函數(shù)名,def定義函數(shù),也叫function/方法/過(guò)程/子程序
</br>
函數(shù)的基礎(chǔ)概念:
- 函數(shù)是一種設(shè)計(jì)工具,它能讓程序員將復(fù)雜的系統(tǒng)分解成可管理的部件, 用于將相關(guān)功能打包并參數(shù)化
- 一組語(yǔ)句的集合通過(guò)一個(gè)名字(函數(shù)名)封裝起來(lái),要想執(zhí)行這個(gè)函數(shù),只需要調(diào)用其函數(shù)名即可
- 可以理解為是一個(gè)帶有名字的,具有一定功能的,用于完成具體工作的代碼塊.
- 當(dāng)程序需要多次執(zhí)行同一個(gè)任務(wù)時(shí),只需要調(diào)用具有該功能的函數(shù)即可.
- 函數(shù)特性:
- 代碼重用
- 保持一致性
- 可擴(kuò)展性
-
Python的函數(shù)可以分為兩類(lèi):
-
內(nèi)置函數(shù):
python內(nèi)置了一系列的常用函數(shù),以便于使用. 我們可以根據(jù)不同的功能需求直接調(diào)用使用.
內(nèi)置函數(shù).png 自定義函數(shù):
我們自己根據(jù)功能需求,以固定的語(yǔ)句格式定義的函數(shù).空函數(shù)
pass語(yǔ)句什么都不做.
實(shí)際上pass是用來(lái)作為占位符,比如現(xiàn)在還沒(méi)想好怎么寫(xiě)函數(shù)的代碼,就可以先放一個(gè)pass,讓代碼能運(yùn)行起來(lái)。def func1(): pass -
- 常見(jiàn)的幾種函數(shù):
- 全局函數(shù) (定義在模塊中,僅限單個(gè)文件)
- 局部函數(shù)(嵌套于其他函數(shù)中)
- lambda函數(shù)(匿名函數(shù))
- 內(nèi)置函數(shù)
</br>
自定義函數(shù)
定義函數(shù)的格式:
python定義函數(shù)使用def關(guān)鍵字,一般格式如下:
def 函數(shù)名(參數(shù)):
'''文檔字串符(docstring),注釋,描述該函數(shù)是做什么的'''
函數(shù)體(代碼行) #這個(gè)函數(shù)要實(shí)現(xiàn)的功能代碼
函數(shù)名的命名規(guī)則:
- 函數(shù)名必須以下劃線或字母開(kāi)頭,可以包含任意字母、數(shù)字或下劃線的組合。不能使用任何的標(biāo)點(diǎn)符號(hào);
- 函數(shù)名是區(qū)分大小寫(xiě)的。
- 函數(shù)名不能是保留字(關(guān)鍵字)
函數(shù)的調(diào)用
定義了函數(shù)之后,就相當(dāng)于有了一個(gè)具有某些功能的代碼
但是,函數(shù)是不會(huì)自動(dòng)執(zhí)行的,想要讓這些代碼能夠執(zhí)行,需要調(diào)用它
調(diào)用函數(shù)很簡(jiǎn)單的,通過(guò) 函數(shù)名()即可完成調(diào)用:
def test1(): # 定義函數(shù)名
print("hello!") # 定義函數(shù)的功能
test1() # 調(diào)用函數(shù)
函數(shù)的文檔說(shuō)明
文檔字串符(docstring)描述該函數(shù)是做什么的,盡量給自定義函數(shù)備注,方便日后查看使用.
def test(a,b):
'''用來(lái)完成對(duì)2個(gè)數(shù)求和'''
print("%d" % (a+b))
test(11,22)
如果執(zhí)行,以下代碼:
help(test)
能夠看到test函數(shù)的相關(guān)說(shuō)明:
Help on function test in module __main__:
test(a, b)
用來(lái)完成對(duì)2個(gè)數(shù)求和
(END)
Tips: 使用三引號(hào)來(lái)構(gòu)成文檔字符串,用來(lái)解釋該函數(shù)的主要功能,這是一個(gè)很好的編碼習(xí)慣.
</br>
函數(shù)的參數(shù)
實(shí)參和形參
實(shí)參是一個(gè)實(shí)實(shí)在在存在的參數(shù),是實(shí)際占用內(nèi)存地址的
形參只是意義上的一種參數(shù),在定義的時(shí)候是不占內(nèi)存地址的.
- 定義時(shí)小括號(hào)中的參數(shù),用來(lái)接收參數(shù)用的,稱(chēng)為 “形參”
- 調(diào)用時(shí)小括號(hào)中的參數(shù),用來(lái)傳遞給函數(shù)用的,稱(chēng)為 “實(shí)參”
形參:形式參數(shù),不是實(shí)際存在,是虛擬變量,在定義函數(shù)和函數(shù)體的時(shí)候使用形參,目的就是在函數(shù)調(diào)用的時(shí)候接收實(shí)參(實(shí)參個(gè)數(shù),類(lèi)型應(yīng)與實(shí)參一一對(duì)應(yīng))
實(shí)參:實(shí)際參數(shù),調(diào)用函數(shù)時(shí)候傳給函數(shù)的變量,可以是常量,變量,表達(dá)式,函數(shù),傳給形參
區(qū)別:形參是虛擬的,不占用內(nèi)存空間,形參變量只有在調(diào)用時(shí)才分配內(nèi)存單元,實(shí)參是一個(gè)變量,占用空間,數(shù)據(jù)傳送單向,實(shí)參傳給形參,不能形參傳給實(shí)參。
def sum_num(a,b): #a,b 是形參
sum_num = a+b
print(sum_num)
sum_num(10,33) #10,33 是實(shí)參
定義時(shí)小括號(hào)中的參數(shù),用來(lái)接收參數(shù)用的,稱(chēng)為 “形參”
調(diào)用時(shí)小括號(hào)中的參數(shù),用來(lái)傳遞給函數(shù)用的,稱(chēng)為 “實(shí)參”
沒(méi)特別指明,形參和實(shí)參必須一一對(duì)應(yīng),多一個(gè)少一個(gè)都報(bào)錯(cuò)
</br>
常用的幾種參數(shù)類(lèi)型:
在Python中可以使用必選參數(shù),默認(rèn)參數(shù),可變參數(shù),關(guān)鍵字參數(shù),這四類(lèi)可以一起使用,或者只使用其中某一些.
但是有多種參數(shù),在定義函數(shù)和傳參的時(shí)候,必須要注意參數(shù)的置放順序:
參數(shù)的順序必須是:
<h6 align = "center" >必備參數(shù),可變(不定長(zhǎng))參數(shù)*args, 默認(rèn)(缺省)參數(shù),可變(不定長(zhǎng))參數(shù)**kargs,關(guān)鍵字參數(shù) </h6>
1. 必備參數(shù)(位置參數(shù))
- 調(diào)用函數(shù)時(shí)根據(jù)函數(shù)定義的參數(shù)位置來(lái)傳遞參數(shù)。
- 所有參數(shù)的順序必須一一對(duì)應(yīng),且少一個(gè)參數(shù)都不可以
def func_1(name,sex):
sex_dict = {1: u'先生', 2: u'女士'}
print ('hello %s %s, welcome to python world!' %(name, sex_dict.get(sex, u'先生')))
func_1("劉",2)
運(yùn)行結(jié)果:hello 劉 女士, welcome to python world!
2. 默認(rèn)參數(shù)(缺省參數(shù))
- 在形參中默認(rèn)有值的參數(shù)
- python為了簡(jiǎn)化函數(shù)的調(diào)用,提供了默認(rèn)參數(shù)機(jī)制
- 用于定義函數(shù),為參數(shù)提供默認(rèn)值,調(diào)用函數(shù)時(shí)可傳可不傳該默認(rèn)參數(shù)的值(注意:所有位置參數(shù)必須出現(xiàn)在默認(rèn)參數(shù)前,包括函數(shù)定義和調(diào)用)
- 在定義有默認(rèn)參數(shù)的函數(shù)時(shí),需要注意以下:
- 必選參數(shù)必須在前面,默認(rèn)參數(shù)在后;
- 設(shè)置何種參數(shù)為默認(rèn)參數(shù)?一般來(lái)說(shuō),將參數(shù)值變化小的設(shè)置為默認(rèn)參數(shù)。
def func_2(name,age=18):
print("我是位置參數(shù):%s"%name,"我是默認(rèn)參數(shù):%s"%age)
func_2("如花") #只給name傳參,會(huì)調(diào)用默認(rèn)參數(shù)的值
func_2("如花",28) #給age傳參,會(huì)覆蓋之前的默認(rèn)參數(shù)
運(yùn)行結(jié)果如下:
我是位置參數(shù):如花 我是默認(rèn)參數(shù):18
我是位置參數(shù):如花 我是默認(rèn)參數(shù):28
3. 可變參數(shù)(不定長(zhǎng)參數(shù))
- 也叫做不定長(zhǎng)參數(shù),動(dòng)態(tài)參數(shù)
- 定義函數(shù)時(shí),有時(shí)候我們不確定調(diào)用的時(shí)候會(huì)傳遞多少個(gè)參數(shù)(不傳參也可以)。此時(shí),可用包裹(packing)位置參數(shù)
*args,或者包裹關(guān)鍵字參數(shù)**kargs,來(lái)進(jìn)行參數(shù)傳遞,會(huì)顯得非常方便。 - 有時(shí)可能需要一個(gè)函數(shù)能處理比當(dāng)初聲明時(shí)更多的參數(shù), 這些可變參數(shù)也被叫做不定長(zhǎng)參數(shù),聲明時(shí)不會(huì)命名。
- 加了星號(hào)(*)的變量args會(huì)存放所有未命名的變量參數(shù),args為元組
- 而加**的變量kwargs會(huì)存放命名參數(shù),即形如key=value的參數(shù), kwargs為字典
(1) 包裹位置傳遞*args
我們傳進(jìn)的所有參數(shù)都會(huì)被args變量收集,它會(huì)根據(jù)傳進(jìn)參數(shù)的位置合并為一個(gè)元組(tuple),args是元組類(lèi)型,這就是包裹位置傳遞。
def func(*args):
....
# func()
# func(a)
# func(a, b, c)
(2)包裹關(guān)鍵字傳遞**kargs
kargs是一個(gè)字典(dict),收集所有關(guān)鍵字參數(shù)
def func(**kargs):
....
# func(a=1)
# func(a=1, b=2, c=3)
(3) 對(duì)于*args和**kwargs在函數(shù)中我們可以稱(chēng)之為參數(shù)組,但是這兩個(gè)還是有區(qū)別的
1:args的功能:------接收N個(gè)位置參數(shù),轉(zhuǎn)換成元組tuple形式
2:kwargs的功能------接收N個(gè)關(guān)鍵字參數(shù),轉(zhuǎn)換成字典dict形式
3:位置參數(shù)一定要在關(guān)鍵字參數(shù)之前,也就是(args,**kwargs)
(4) *args和**kwargs一起用, 功能會(huì)更強(qiáng)大
可以兩個(gè)一起使用:功能更加的強(qiáng)大:會(huì)把無(wú)參數(shù)名臣的封裝成一個(gè)tuple 把有參數(shù)名稱(chēng)的封裝成一個(gè)字典;并且,arg必須在**kwargs前面
# def show(*args ,**kwargs):
# print(args,kwargs)
# show(11,22,33,nn=22,kk=33)
值得注意的是雖然*args和**kwargs會(huì)把我們給他的參數(shù)封裝成列表和字典,但是如果我們?cè)诮o定實(shí)際參數(shù)的時(shí)候給的是一個(gè)列表或者是字典,只是表示只有一個(gè)實(shí)參,而不是列表和字典里面的值;如果想要實(shí)現(xiàn)這個(gè)功能,那么我們就需要在列表或者字典前面加上*或者**就能實(shí)現(xiàn)了;
4. 關(guān)鍵字參數(shù)
用于函數(shù)調(diào)用,通過(guò)“鍵-值”形式加以指定。可以讓函數(shù)更加清晰、容易使用,同時(shí)也清除了參數(shù)的順序需求。
#以下是用關(guān)鍵字參數(shù)正確調(diào)用函數(shù)的實(shí)例
func_01('tanggu', sex=1)
func_01(1, name='tanggu')
func_01(name='tanggu', sex=1)
func_01(sex=1, name='tanggu')
# 以下是錯(cuò)誤的調(diào)用方式
func_01(name='tanggu', 1)
func_01(sex=1, 'tanggu')
tips:雖然函數(shù)參數(shù)類(lèi)型很多,但不要同時(shí)使用太多的組合,否則函數(shù)接口的可理解性很差.
</br>
函數(shù)的返回值
函數(shù)的返回值是函數(shù)重要的組成部分。函數(shù)的根本在于實(shí)現(xiàn)程序的部分功能,所以很多時(shí)候我們需要將函數(shù)執(zhí)行后的結(jié)果返回給程序再由程序作出進(jìn)一步的操作??梢哉f(shuō)是函數(shù)的返回值令函數(shù)與函數(shù)之間,函數(shù)與主程序之間更加緊密的聯(lián)系起來(lái)。
函數(shù)的返回值:
- 在Python的函數(shù)中都有一個(gè)返回值,默認(rèn)為None。也可以使用return value語(yǔ)句來(lái)定義一個(gè)且只能定義一個(gè)可為任意類(lèi)型的返回值。但是我們能夠返回一個(gè)序列類(lèi)型的對(duì)象,來(lái)實(shí)現(xiàn)返回多個(gè)值的效果。
- 函數(shù)外部的代碼要想獲取函數(shù)的執(zhí)行結(jié)果,就可以在函數(shù)里面用return語(yǔ)句,把結(jié)果返回.
- return 代表一個(gè)函數(shù)的終止,函數(shù)在執(zhí)行過(guò)程中只要遇到return語(yǔ)句,就會(huì)停止執(zhí)行,并返回結(jié)果.如果return 后面帶一個(gè)print 或者return ,則后面的不執(zhí)行
- 如果未在函數(shù)中指定return,那么這個(gè)函數(shù)的返回值就是None
def func_2(name,age=18):
print("我是位置參數(shù):%s"%name,"我是默認(rèn)參數(shù):%s"%age)
func_2("如花") #只給name傳參
func_2("如花",28) #給age傳參,會(huì)覆蓋之前的默認(rèn)參數(shù)
def without_return(a,b): #定義一個(gè)沒(méi)有return的函數(shù)
print(a+b)
print(a-b)
def with_return(a,b): #定義一個(gè)有return的函數(shù)
return a+b
return a-b
result1 = without_return(5,10) #調(diào)用上邊定義的沒(méi)有return的函數(shù)
result2 = with_return(5,10) #調(diào)運(yùn)上邊定義的有return的函數(shù)
print("沒(méi)有返回值的函數(shù):",result1)
print("有返回值的函數(shù):",result2)
上段代碼運(yùn)行后,結(jié)果如下:
15
-5
沒(méi)有返回值的函數(shù): None
有返回值的函數(shù): 15
[注意:]
- 定義的函數(shù)沒(méi)有返回值,調(diào)用時(shí)接用變量收到的是None
- 函數(shù)體里的代碼執(zhí)行完后會(huì)回到函數(shù)調(diào)用的地
- 函數(shù)體里有多個(gè)return語(yǔ)法不會(huì)報(bào)錯(cuò),但是不能做到返回多個(gè)值的操作
- 函數(shù)執(zhí)行到return語(yǔ)句表示函數(shù)執(zhí)行結(jié)束,后邊有再多也不會(huì)執(zhí)行了
接收多個(gè)rerun值
理論上,return只能返回一個(gè)值; 如果想要返回多個(gè)值,可以考慮把多個(gè)值放在列表,元祖,字典里邊.
def return_value():
print('返回多個(gè)值')
return [1,3,5]
#return (1,3,5)
#return {'a':1,'b':2,'c':3}
result = return_value()
print(result)
上述代碼運(yùn)行結(jié)果:
返回多個(gè)值
[1, 3, 5]
- return后面可以是元組,列表、字典等,只要是能夠存儲(chǔ)多個(gè)數(shù)據(jù)的類(lèi)型,就可以一次性返回多個(gè)數(shù)據(jù)
- 如果return后面有多個(gè)數(shù)據(jù),那么默認(rèn)是元組
函數(shù)的嵌套調(diào)用
- 函數(shù)的嵌套,在函數(shù)里邊再定義一個(gè)函數(shù)
- 調(diào)用可以理解為,是在一個(gè)函數(shù)里調(diào)用了其他函數(shù)
- 嵌套函數(shù)不能在外部使用,只能在函數(shù)內(nèi)部使用
def show_msg():
print("show_msg")# 在函數(shù)里面定義的函數(shù)就是嵌套函數(shù)
def show():
print("我是函數(shù)體里面的內(nèi)部函數(shù)->>子函數(shù)")
show() # 在函數(shù)體里面調(diào)用嵌套函數(shù)
show_msg() # 調(diào)用函數(shù)
# 注意點(diǎn): 嵌套函數(shù)不能再函數(shù)外使用,只能在函數(shù)內(nèi)部使用
上述代碼運(yùn)行結(jié)果:
show_msg
我是函數(shù)體里面的內(nèi)部函數(shù)->>子函數(shù)
函數(shù)嵌套的小應(yīng)用: 使用冰箱:
- 在實(shí)際開(kāi)發(fā)中,使用函數(shù)的嵌套可以大大的提高代碼的可讀性
def use_ice_box(eat):
# 嵌套函數(shù)的作用,把函數(shù)拆分成不同的功能函數(shù)
# 打開(kāi)冰箱
def open_ice_box():
print("打開(kāi)冰箱門(mén)")
# 向冰箱放入食物
def put_eat(eat):
print("把%s放入冰箱" % eat)
# 關(guān)閉冰箱
def close_ice_box():
print("關(guān)閉冰箱門(mén)")
open_ice_box()
put_eat(eat)
close_ice_box()
use_ice_box("蘋(píng)果")
局部變量和全局變量,函數(shù)的作用域
變量作用域
LEGB原則
- Python中,程序的變量并不是在哪個(gè)位置都可以訪問(wèn)的,訪問(wèn)權(quán)限決定于這個(gè)變量是在哪里賦值的。
- 變量的作用域決定了在哪一部分程序可以訪問(wèn)哪個(gè)特定的變量名稱(chēng)。
- Python的作用域一共有4種,如下:
- L ( Local):函數(shù)內(nèi)的區(qū)域,包括局部變量和形參。
- E(Enclosing):外面嵌套函數(shù)區(qū)域,常見(jiàn)的是閉包函數(shù)外的函數(shù)。
- G( Global):全局作用域。
- B( Built-in): 內(nèi)建作用域。
- Python中變量是采用L -> E->G一>B的規(guī)則查找
- 當(dāng)Python檢索變量的時(shí)候,先是在局部中查找,如果找不到,便會(huì)去局部外的局部找(例如閉包),再找不到就會(huì)去全局找,再者去內(nèi)中找。
局部變量
- 局部變量,就是在函數(shù)內(nèi)部定義的變量
- 作用范圍:只能在函數(shù)體里面使用
- 局部變量的作用: 臨時(shí)存儲(chǔ)函數(shù)體里面的所需要的數(shù)據(jù)的
- 局部變量等函數(shù)執(zhí)行完成以后會(huì)釋放
- 如果函數(shù)里面return了一個(gè)返回值,那么等外界使用完成以后該返回值以后才會(huì)釋放
全局變量和關(guān)鍵字global
- 如果一個(gè)變量,既能在一個(gè)函數(shù)中使用,也能在其他的函數(shù)中使用,這樣的變量就是全局變量
- 也可以理解成在函數(shù)外定義的變量就是全局變量
num1 = 1 #<--全局變量
def funcA():
num1 = 3 #<--- 局部變量.可以理解為定義了一個(gè)局部變量,只不過(guò)局部變量的名字和全局變量的名字相同而已,不是同一個(gè)變量
print("funcA里的變量:",num1)
def funcB():
print("funcB里的變量:",num1)
funcA()
funcB()
上述代碼運(yùn)行結(jié)果:
funcA里的變量: 3
funcB里的變量: 1
使用關(guān)鍵字global修改全局變量
當(dāng)內(nèi)部作用域想修改外部作用域的變量時(shí),要用到global和nonlocal關(guān)鍵字了。
global關(guān)鍵字用來(lái)在函數(shù)或其他局部作用域中使用全局變量。但是如果不修改全局變量也可以不使用global關(guān)鍵字。
- 如果在函數(shù)中出現(xiàn)
global 全局變量名字, 那么這個(gè)函數(shù)中即使出現(xiàn)和全局變量名相同的變量名 = 數(shù)據(jù)也理解為對(duì)全局變量進(jìn)行修改,而不是定義局部變量 - global 表示聲明要修改全局變量
- 如果在一個(gè)函數(shù)中需要對(duì)多個(gè)全局變量進(jìn)行修改,那么可以使
global a, b,...n - 也可以多次用global聲明,
global a,global b
# 修改全局變
num1 = 1
def funcA():
global num1 # <-- 表示聲明要修改全局變量
num1 = 3
print("funcA里的變量:",num1)
def funcB():
print("funcB里的變量:",num1)
funcA()
funcB()
運(yùn)行結(jié)果:
funcA里的變量: 3
funcB里的變量: 3
在Python中,以上邊代碼為例,如果在函數(shù)內(nèi)部對(duì)全局變量num1進(jìn)行修改, Python會(huì)把變量num1當(dāng)做是局部變量,為了使全局變量生效,我們可以在函數(shù)內(nèi)使用global關(guān)鍵字進(jìn)行聲明.
如果沒(méi)有對(duì)變量num1進(jìn)行全局變量申明,運(yùn)行程序后會(huì)報(bào)錯(cuò):UnboundLocalError: local variable 'a' referenced before assignment
nonlocal關(guān)鍵字
nonlocal是在Python3.0中新增的關(guān)鍵字,python2.x不提供支持。
使用nonlocal關(guān)鍵字可以在一個(gè)嵌套的函數(shù)中修改嵌套作用域中的變量。
示例一:
def FinalResult():
result = 0
print("外部函數(shù)的變量result的值為:"+ str(result))
def sumResult():
result = 12
print("內(nèi)部函數(shù)的變量result的值為"+str(result))
sumResult()
FinalResult()
上述示例一代碼運(yùn)行結(jié)果如下:
外部函數(shù)的變量result的值為:0
內(nèi)部函數(shù)的變量result的值為12
示例二:
def FinalResult():
result = 0
#print("外部函數(shù)的變量result的值為:"+ str(result))
def sumResult():
result = 12
print("內(nèi)部函數(shù)的變量result的值為"+str(result))
sumResult()
print("外部函數(shù)的變量result的值為:"+ str(result))
FinalResult()
上述示例二代碼運(yùn)行結(jié)果如下:
內(nèi)部函數(shù)的變量result的值為12
外部函數(shù)的變量result的值為:0
注意 通過(guò)上述示例可以看出, 嵌套在函數(shù)FinalResult內(nèi)部的內(nèi)嵌函數(shù)sumResult中, 我們對(duì)變量result的賦值,其實(shí)本質(zhì)是重新創(chuàng)建了一個(gè)新的變量,而不是外部函數(shù)FinalResult中result=0這條語(yǔ)句的重新賦值.
(2) 通過(guò)調(diào)換外部函數(shù)的print語(yǔ)句和調(diào)用內(nèi)部函數(shù)sumResult兩條語(yǔ)句的先后位置, 可以對(duì)比發(fā)現(xiàn), 內(nèi)部函數(shù)的變量賦值,無(wú)論什么時(shí)候被調(diào)用都沒(méi)有對(duì)外部的同名變量造成影響.
示例三:
- 使用
nonlocal關(guān)鍵字 - 在內(nèi)部嵌套的函數(shù)
sumResult中使用了nonlocal關(guān)鍵字,就會(huì)告訴Python在外部的函數(shù)FinalResult中使用嵌套作用域中的變量result - 這樣,當(dāng)我們?cè)趦?nèi)嵌函數(shù)中對(duì)變量
result進(jìn)行修改時(shí),會(huì)直接影響到整個(gè)嵌套作用域中的result變量
def FinalResult():
result = 0
def sumResult():
nonlocal result
result = 12
print("內(nèi)部函數(shù)的變量result的值為"+str(result))
sumResult()
print("外部函數(shù)的變量result的值為:"+ str(result))
FinalResult()
上述示例三代碼運(yùn)行結(jié)果如下:
內(nèi)部函數(shù)的變量result的值為12
外部函數(shù)的變量result的值為:12
- 使用
global關(guān)鍵字修飾的變量之前可以不存在 - 使用
nonlocal關(guān)鍵字修飾的變量之前不存在,運(yùn)行會(huì)報(bào)錯(cuò):SyntaxError: no binding for nonlocal 'result' found
[小總結(jié):]
一個(gè)變量在函數(shù)體外,一個(gè)變量在函數(shù)體內(nèi), 改變量用global.
一個(gè)變量在內(nèi)嵌函數(shù)里,一個(gè)變量在包裹內(nèi)嵌函數(shù)的外層函數(shù)里,改變量nonlocal
多層嵌套函數(shù)和函數(shù)外同用一個(gè)變量,用global申明.
(這段代碼為實(shí)驗(yàn),不確定全適用,也有可能方法有點(diǎn)蠢,因?yàn)楹髞?lái)發(fā)現(xiàn),貌似可以用return( ̄. ̄))
- 申明變量的原則是,哪里用就在哪里申明.
假設(shè)我們有一個(gè)變量result,這個(gè)變量會(huì)在函數(shù)體外使用,也會(huì)在多層嵌套的函數(shù)的某幾個(gè)層里使用.
我們希望達(dá)到的效果是:在任何一個(gè)地方修改變量result,所有位置的變量result的值都改變,即在之后無(wú)論在函數(shù)外還是函數(shù)內(nèi)再調(diào)用這個(gè)變量result,得到的是最新的result的值.具體實(shí)現(xiàn)如下:
示例四:
result = 10 # <== 函數(shù)外的變量result
print("函數(shù)外的result變量:"+str(result)) #<== 第一條print執(zhí)行語(yǔ)句
def FinalResult():
global result <== 申明result為全局變量, 這里如果不申明, 知result程序默認(rèn)不是同一個(gè)變量,只是同名.
result = 11
print("外部函數(shù)的變量result的值為:"+ str(result)) # <== 第2條print執(zhí)行語(yǔ)句
def sumResult():
#nonlocal resul # <== 這里如果用nonlocal,會(huì)報(bào)錯(cuò)
global result #用global申明result為全局變量
result = 12
print("內(nèi)部函數(shù)的變量result的值為"+str(result)) # <== 第3條print執(zhí)行語(yǔ)句
sumResult()
print("調(diào)用完最里層函數(shù)后,再次打印外部函數(shù)的變量result的值為:"+ str(result)) #<== 第四條print執(zhí)行語(yǔ)句
FinalResult()
print("調(diào)用完最里層函數(shù)后,再次打印函數(shù)外的result變量:",result) #<== 第5條print執(zhí)行語(yǔ)句
[小總結(jié):]
- 我的目的是在最里層的函數(shù)sumResult里修改變量
result為12,之后再調(diào)用它的外層函數(shù)中的變量result或再次調(diào)用整個(gè)函數(shù)體外的變量result時(shí), 這個(gè)result的值都是12 - 需要兩次global申明, 遵循'申明變量的原則是,哪里用就在哪里申明'
- 如果只在內(nèi)層函數(shù)中g(shù)lobal申明,但外層函數(shù)中的
result不申明, 再次調(diào)用,函數(shù)體外邊的這個(gè)result變?yōu)?2了,外層函數(shù)中的result的值依舊是11.
- 如果只在內(nèi)層函數(shù)中g(shù)lobal申明,但外層函數(shù)中的
</br>
函數(shù)的拆包 & 交換變量值
- 拆包:把容器中的每一個(gè)數(shù)據(jù)拆分到不同變量進(jìn)行保存數(shù)據(jù)
- 容器:列表,字典, 元組, 字符串
- 拆包時(shí)要注意,需要拆的數(shù)據(jù)的個(gè)數(shù)要與變量的個(gè)數(shù)相同,一一對(duì)應(yīng),不能多,否則程序會(huì)異常
拆包
list1 = [2,3,4]
a,b,c =list1 # 拆包的時(shí)候需要一一對(duì)應(yīng),不能多
print(a, b)
tuple1 = ("張三", "李四")
name1, name2 = tuple1
print(name1, name2)
dict1 = {"name": "小新", "age": 5}.values()
value1, value2 = dict1
print(value1, value2)
str1 = "apple"
a, b, c, d, e, = str1
print(a, b, c,d,e)
上述代碼運(yùn)行結(jié)果:
2 3
張三 李四
小新 5
a p p l e
[注意:]變量名的數(shù)量一定要和容器內(nèi)元素的數(shù)量一模一樣,否則會(huì)報(bào)錯(cuò).
例: alueError: not enough values to unpack (expected 6, got 5),ValueError: too many values to unpack (expected 4)
交換兩個(gè)變量的值
- 一般用法:
- 通用的交換變量的方式:定義臨時(shí)變量
num1 = 1
num2 = 2
num3 = num1
num1 = num2
num2 = num3
print(num1, num2)
- Python特有的用法
num1 = 1
num2 = 2
num1, num2 = num2, num1
print(num1, num2)
多函數(shù)程序的基本使用流程
一般在實(shí)際開(kāi)發(fā)過(guò)程中,一個(gè)程序往往由多個(gè)函數(shù))組成,并且多個(gè)函數(shù)共享某些數(shù)據(jù),這種場(chǎng)景是經(jīng)常出現(xiàn)的,因此下面來(lái)總結(jié)下,多個(gè)函數(shù)中共享數(shù)據(jù)的幾種方式:
- 使用全局變量
- 使用函數(shù)的返回值、參數(shù)
- 函數(shù)嵌套調(diào)用
- 使用全局變量
- 多個(gè)函數(shù)可以使用同一個(gè)全局變量
- 全局變量可以在函數(shù)里共享數(shù)據(jù)
score = 100
# 修改全局變量數(shù)據(jù)的函數(shù)
def modify():
# 聲明修改全局變量
global score
# 修改全局變量
score = 90
print("modify:", score)
# 獲取全局變量修改后的數(shù)據(jù)
def show():
# 獲取全局變量的數(shù)據(jù)
print("獲取全局變量修最新的數(shù)據(jù):", score)
modify()
show()
上述代碼運(yùn)行后的結(jié)果:
modify: 90
獲取全局變量修最新的數(shù)據(jù): 90
- 使用函數(shù)的返回值、參數(shù)
- 函數(shù)的返回值可以作為其他函數(shù)的參數(shù)
def return_value():
return "哈哈"
def show_info(msg):
print(msg)
# 1.獲取函數(shù)的返回值
value = return_value()
# 2.把函數(shù)的返回值作為其他函數(shù)的參數(shù)使用
show_info(value)
上述代碼的運(yùn)行結(jié)果:
哈哈
- 函數(shù)嵌套調(diào)用
def test1():
# 通過(guò)return將一個(gè)數(shù)據(jù)結(jié)果返回
return 20
def test2():
# 1. 先調(diào)用test1并且把結(jié)果返回來(lái)
result = test1()
# 2. 對(duì)result進(jìn)行處理
print(result)
# 調(diào)用test2時(shí),完成所有的處理
test2()
上述代碼運(yùn)行結(jié)果:
20
總結(jié):函數(shù)使用注意事項(xiàng)
1. 自定義函數(shù)
-
函數(shù)名不能重復(fù)
- 如果在同一個(gè)程序中出現(xiàn)了多個(gè)相同函數(shù)名的函數(shù),那么在調(diào)用函數(shù)時(shí)就會(huì)出現(xiàn)問(wèn)題,所以要避免名字相同
- 還有一點(diǎn) 不僅要避免函數(shù)名之間不能相同,還要避免 變量名和函數(shù)名相同的,否則都會(huì)出現(xiàn)問(wèn)題
一個(gè)函數(shù)到底有沒(méi)有返回值,就看有沒(méi)有return,因?yàn)橹挥衦eturn才可以返回?cái)?shù)據(jù)
在開(kāi)發(fā)中往往根據(jù)需求來(lái)設(shè)計(jì)函數(shù)需不需要返回值
函數(shù)中,可以有多個(gè)return語(yǔ)句,但是只要執(zhí)行到一個(gè)return語(yǔ)句,那么就意味著這個(gè)函數(shù)的調(diào)用完成
在調(diào)用函數(shù)時(shí),如果需要把一些數(shù)據(jù)一起傳遞過(guò)去,被調(diào)用函數(shù)就需要用參數(shù)來(lái)接收
參數(shù)列表中變量的個(gè)數(shù)根據(jù)實(shí)際傳遞的數(shù)據(jù)的多少來(lái)確定
無(wú)參數(shù)、無(wú)返回值
def 函數(shù)名():
語(yǔ)句
無(wú)參數(shù)、有返回值
def 函數(shù)名():
語(yǔ)句
return 需要返回的數(shù)值
有參數(shù)、無(wú)返回值
def 函數(shù)名(形參列表):
語(yǔ)句
有參數(shù)、有返回值
def 函數(shù)名(形參列表):
語(yǔ)句
return 需要返回的數(shù)值
2.調(diào)用函數(shù)
調(diào)用的方式為:函數(shù)名([實(shí)參列表])
- 如果調(diào)用的函數(shù) 在定義時(shí)有形參,那么在調(diào)用的時(shí)候就應(yīng)該傳遞參數(shù)
- 調(diào)用時(shí),實(shí)參的個(gè)數(shù)和先后順序應(yīng)該和定義函數(shù)中要求的一致
- 如果調(diào)用的函數(shù)有返回值,那么就可以用一個(gè)變量來(lái)進(jìn)行保存這個(gè)值
3.作用域
- 在一個(gè)函數(shù)中定義的變量,只能在本函數(shù)中用(局部變量)
- 在函數(shù)外定義的變量,可以在所有的函數(shù)中使用(全局變量)
參考資料:
- 傳智博客講義
- 廖雪峰老師的教程
- cnblog-python的位置參數(shù)、默認(rèn)參數(shù)、關(guān)鍵字參數(shù)、可變參數(shù)區(qū)別
- cnblog-python 函數(shù)參數(shù)類(lèi)型
- 戰(zhàn)爭(zhēng)熱誠(chéng)的博客
擴(kuò)展閱讀:
cnblog-Python進(jìn)階-函數(shù)默認(rèn)參數(shù)
