函數的返回值:
Python函數使用return語句返回"返回值"
所有函數都有返回值,如果沒有return語句,隱式調用return None
return語句並不一定是函數的語句塊的最後一條語句
一個函數可以存在多個return語句,但是隻有一條可以被執行;如果沒有一條return語句被執行到,
隱式調用return None
如果有必要,可以顯示調用return None,可以簡寫return
如果函數被掃行了return語句,函數就會返回,當前被執行的return語句之後的其它語句就不會被執行了
作用:結束函數調用、返回值
舉例:
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變量在上級作用域而非本地作用域中定義;
代碼可以正常使用,且形成閉包;