week04_python函数返回值、作用域
函數(shù)的返回值:
? Python函數(shù)使用return語句返回"返回值"
? 所有函數(shù)都有返回值,如果沒有return語句,隱式調(diào)用return None
? return語句并不一定是函數(shù)的語句塊的最后一條語句
? 一個函數(shù)可以存在多個return語句,但是只有一條可以被執(zhí)行;如果沒有一條return語句被執(zhí)行到,
隱式調(diào)用return None
? 如果有必要,可以顯示調(diào)用return None,可以簡寫return
? 如果函數(shù)被掃行了return語句,函數(shù)就會返回,當(dāng)前被執(zhí)行的return語句之后的其它語句就不會被執(zhí)行了
? 作用:結(jié)束函數(shù)調(diào)用、返回值
舉例:
def?showplus(x):print(x)return?x?+?1return?x?+?2print(showplus(5))#?只執(zhí)行第一條returndef?guess(x):if?x?>?3:return?">?3"else:return?"<=?3"print(guess(2))#?條件滿足,只執(zhí)行其中一條returndef?fn(x):for?i?in?range(x):if?i?>?3:return?ielse:print("{}?is?not?greater?than?3".format(i))print(fn(5))#?打印什么? print(fn(3))#?打印什么?函數(shù)不能同時返回多個值:
def?showlist():return?[1,?3,?5]print(showlist())?#[1,?3,?5]?指明返回一個列表,是一個列表對象def?showlist():return?1,?3,?5print(showlist())?#(1,?3,?5)?看似返回多個值,隱式被python封裝成了一個元組函數(shù)的嵌套:
? 在一個函數(shù)中定義了另一個函數(shù)
def?outer():def?inner():print("inner")print("outer")outer()#?outer inner()#?NameError:?name?'inner'?is?not?defined函數(shù)有可見范圍,這就是作用域的概念;
內(nèi)部函數(shù)不能被外部直接使用,會拋NameError異常;
作用域###
? 一個標(biāo)識符的可見范圍,這就是標(biāo)識符的作用域。一般常說的是變量的作用域
對比一下,下面2個函數(shù),x到底是可見還是不可見?(1) x?=?5def?foo():print(x)foo()#?5(2) x?=?5def?foo():x?+=?1print(x)foo()#?UnboundLocalError:?local?variable?'x'?referenced?before?assignment全局作用域:
? 在整個程序運(yùn)行環(huán)境中都可見;
局部作用域:
? 在函數(shù)、類等內(nèi)部可見;
? 局部變量使用范圍不能超過其所在的的局部作用域;
def?fn1():x?=?1?#?局部作用域,在fn1內(nèi)def?fn2():print(x)#?x可見嗎?print(x)#?x可見嗎?嵌套結(jié)構(gòu):
從上面的例子中可以看出:
? 外層變量作用域在內(nèi)層作用域可見;
? 內(nèi)層作用域inner中,如果定義了o = 97 ,相當(dāng)于當(dāng)前作用域中重新定義了一個新的變量o,但是
這個o并沒有覆蓋外層作用域outer中的o
x?=?5 def?foo():#?y?=?x?+?1x?+=?1#?UnboundLocalError:?local?variable?'x'?referenced?before?assignmentprint(x) foo()x?+=?1?其實是?x?=?x?+?1 相當(dāng)于在foo內(nèi)部定義一個局部變量x,那么foo內(nèi)部所有x都是這個局部變量了; 但是這個x還沒有完全賦值,就被右邊拿來做加1操作了; 該如何解決???全局變量global
x?=?5 def?foo():global?xx?+=?1print(x)foo()使用global關(guān)鍵字的變量,將foo內(nèi)的x聲明為使用外部的全局作用域中定義的x;? 全局作用域中必須有x的定義 如果全局作用域中沒有x定義會怎么樣???x?=?5def?foo():global?xx?=?10x?+=?1#?會報錯嗎?print(x)#?打印什么?print(x) foo()使用global關(guān)鍵字的變量,將foo內(nèi)的x聲明為使用外部的全局作用域中定義的x;?
但是,x = 10 賦值即定義,x在內(nèi)部作用域為一個外部作用域的變量賦值,所以x += 1不會報錯。?
注意:這里x的作用域還是全局的;
global總結(jié):
? x += 1這種是特殊形式產(chǎn)生的錯誤的原因?先引用后賦值,而python動態(tài)語言是賦值和算定義;
? 才能被引用。解決方法,在這條語句前增加x = 0之類的賦值語句,或者使用global告訴內(nèi)部作
? 用域,去全局作用域查找變量定義;
? 內(nèi)部作用域使用x = 5之類的賦值語句會重新定義局部作用域使用的變量x,但是,一旦這個作用
? 域中使用global聲明x為全局的,那么x = 5相當(dāng)于在為全局作用域的變量x賦值;
global使用原則:
? 外部作用域變量會內(nèi)部作用域可見,但也不要在這個內(nèi)部的局部作用域中直接使用,因為
? 函數(shù)的目的就是為了封裝,盡量與外界隔離;
? 如果函數(shù)需要使用外部全局變量,請使用函數(shù)的形參傳參解決;
? 一句話:不用global。學(xué)習(xí)它就是為了深入理解變量的作用域;
閉包#
? 自由變量:未在本地作用域中定義的變量。例如定義在內(nèi)存函數(shù)外的外層函數(shù)的作用域中的變量;
? 閉包:就是一個概念,出現(xiàn)在嵌套函數(shù)中,指的是內(nèi)層函數(shù)引用到了外層函數(shù)的自由變量,就形成
了閉包。很多語言都有這個概念,最熟悉就是JavaScript
def?counter():c?=?[0]def?inc():c[0]?+=?1return?c[0]return?incfoo?=?counter() print(foo(),?foo()) c?=?100 print(foo())代碼解析:
? 第4行不會報錯,因為c已經(jīng)在counter函數(shù)中定義過了。而inc中的使用方式是為c的元素修改值,而不是重新定義。
? 第8行 會打印 1 2
? 第10行會打印 3
? 第9行的c和counter中的c不一樣,而inc引用的是自由變量正式counter的變量c;?
這就是python2中實現(xiàn)閉包的方式,python3還可以使用nonlocal關(guān)鍵字
nonlocal關(guān)鍵字
? 使用nonlocal關(guān)鍵字,將變量標(biāo)記為不在本地作用域定義,而是上級的某一級局部作用域中定義,但不能是
全局作用域中定義
def?counter():count?=?0def?inc():nonlocal?countcount?+=?1return?countreturn?inc foo?=?counter() print(foo()) print(foo())代碼解析:
? count是外層函數(shù)的局部變量,被內(nèi)部函數(shù)引用;
? 內(nèi)部函數(shù)使用nonlocal關(guān)鍵字聲明count變量在上級作用域而非本地作用域中定義;
? 代碼可以正常使用,且形成閉包;
變量名解析原則LEGB
Local,本地作用域、局部作用域的local命名空間。函數(shù)調(diào)用時創(chuàng)建,調(diào)用結(jié)束消亡。
Enclosing,Python2.2時引入嵌套函數(shù),實現(xiàn)了閉包,這個就是嵌套函數(shù)的外部函數(shù)的命名空間。
Global,全局作用域,即一個模塊的命名空間。模塊被import時創(chuàng)建,解釋器退出時消亡。
Build-in,內(nèi)置模塊的命名空間,生命周期從python解釋器啟動時創(chuàng)建到解釋器退出時消亡。
所以一個名詞的查找順序就是LEGB
轉(zhuǎn)載于:https://blog.51cto.com/limingyu/2165659
總結(jié)
以上是生活随笔為你收集整理的week04_python函数返回值、作用域的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java FileReader Inpu
- 下一篇: python进程和线程中的两个锁