函數的返回值:python
Python函數使用return語句返回"返回值"閉包
全部函數都有返回值,若是沒有return語句,隱式調用return Noneide
return語句並不必定是函數的語句塊的最後一條語句函數
一個函數能夠存在多個return語句,可是隻有一條能夠被執行;若是沒有一條return語句被執行到,學習
隱式調用return Noneui
若是有必要,能夠顯示調用return None,能夠簡寫returnspa
若是函數被掃行了return語句,函數就會返回,當前被執行的return語句以後的其它語句就不會被執行了orm
做用:結束函數調用、返回值對象
舉例:生命週期
def showplus(x): print(x) return x + 1 return x + 2 print(showplus(5))# 只執行第一條return def guess(x): if x > 3: return "> 3" else: return "<= 3" print(guess(2))# 條件知足,只執行其中一條return def fn(x): for i in range(x): if i > 3: return i else: 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, 5 print(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 = 5 def foo(): print(x) foo()# 5 (2) x = 5 def foo(): x += 1 print(x) foo()# UnboundLocalError: local variable 'x' referenced before assignment
全局做用域:
在整個程序運行環境中均可見;
局部做用域:
在函數、類等內部可見;
局部變量使用範圍不能超過其所在的的局部做用域;
def fn1(): x = 1 # 局部做用域,在fn1內 def fn2(): print(x)# x可見嗎? print(x)# x可見嗎?
嵌套結構:
對比下面兩個代碼中變量o的差異: (1). def outer1(): o = 65 def inner(): print("inner {}".format(o)) print(chr(o)) print("outer {}".format(o)) inner() outer1() (2). def outer2(): o = 65 def inner(): o = 97 print("inner {}".format(o)) print(chr(o)) print("outer {}".format(o)) inner() outer2()
從上面的例子中能夠看出:
外層變量做用域在內層做用域可見;
內層做用域inner中,若是定義了o = 97 ,至關於當前做用域中從新定義了一個新的變量o,可是
這個o並無覆蓋外層做用域outer中的o
x = 5 def foo(): # y = x + 1 x += 1# UnboundLocalError: local variable 'x' referenced before assignment print(x) foo() x += 1 實際上是 x = x + 1 至關於在foo內部定義一個局部變量x,那麼foo內部全部x都是這個局部變量了; 可是這個x尚未徹底賦值,就被右邊拿來作加1操做了; 該如何解決???
全局變量global
x = 5 def foo(): global x x += 1 print(x) foo() 使用global關鍵字的變量,將foo內的x聲明爲使用外部的全局做用域中定義的x; 全局做用域中必須有x的定義 若是全局做用域中沒有x定義會怎麼樣???
x = 5 def foo(): global x x = 10 x += 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] += 1 return c[0] return inc foo = 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 = 0 def inc(): nonlocal count count += 1 return count return inc foo = counter() print(foo()) print(foo())
代碼解析:
count是外層函數的局部變量,被內部函數引用;
內部函數使用nonlocal關鍵字聲明count變量在上級做用域而非本地做用域中定義;
代碼能夠正常使用,且造成閉包;
變量名解析原則LEGB
Local,本地做用域、局部做用域的local命名空間。函數調用時建立,調用結束消亡。
Enclosing,Python2.2時引入嵌套函數,實現了閉包,這個就是嵌套函數的外部函數的命名空間。
Global,全局做用域,即一個模塊的命名空間。模塊被import時建立,解釋器退出時消亡。
Build-in,內置模塊的命名空間,生命週期從python解釋器啓動時建立到解釋器退出時消亡。
因此一個名詞的查找順序就是LEGB