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