1.global關鍵字
前面說到在函數中修改全局變量,是不會成功的,因為Python的shadowing機制,會自動屏蔽,只會在函數內部創建一個跟全局變量名字一樣的局部變量。
>>> count = 10
>>> def fun1(): count = 5 print('函數fun1()正在被調用') >>> count 10 >>>
為了在函數內部能夠成功修改全部變量,使用global關鍵字,如下:
>>> count = 10 >>> def fun2(): global count ##使用global關鍵字 count = 5 print('函數fun2()正在被調用') >>> fun2() 函數fun2()正在被調用 >>> count 5 >>>
2.內嵌函數
內嵌函數中:內部函數fun2()的作用域(定義、調用)是在整個外部函數fun1()之內的
>>> def fun1(): ##外部函數 print('函數fun1()正在被調用') def fun2(): ##內部函數 print('函數fun2()正在被調用') fun2()
>>> fun1() 函數fun1()正在被調用 函數fun2()正在被調用 >>>
出了fun1()這個函數,就不可以對fun2()進行調用,Python最新版可以在外部函數之外調用內部函數
>>> def fun1(): print('函數fun1()正在被調用') def fun2(): print('函數fun2()正在被調用') fun2() >>> fun1() 函數fun1()正在被調用 函數fun2()正在被調用 >>> fun2() 函數fun2()正在被調用 >>>
3.閉包
①.定義:如果在一個內部函數里,對在外部作用域的變量的引用,則內部函數就叫做閉包。
>>> def funX(x): def funY(y): return x * y return funY >>> funX(8) <function funX.<locals>.funY at 0x0429DFA0>>>> i = funX(8) >>> type(i) <class 'function'> ## i 是個函數 >>> i(5) 40 >>> funX(8)(5) 40
在閉包中,外部不能調用(接上面的例子):
>>> funY(5) Traceback (most recent call last): File "<pyshell#41>", line 1, in <module> funY(5) NameError: name 'funY' is not defined >>>
2.內嵌函數中,內部函數不能修改非全局變量的外部變量,例如:
>>> def fun1(): x = 5 ##對於內部函數fun2()來說,x是非全局變量的外部變量 def fun2(): x *= x return x return fun2() >>> fun1() Traceback (most recent call last): File "<pyshell#50>", line 1, in <module> fun1() File "<pyshell#49>", line 6, in fun1 return fun2() File "<pyshell#49>", line 4, in fun2 x *= x UnboundLocalError: local variable 'x' referenced before assignment ##局部變量x在定義之前不能被使用 >>>
nonlocal關鍵字的使用
>>> def fun1(): x = 5 def fun2(): nonlocal x x *= x return x return fun2() >>> fun1() 25 >>>
作業
0.如果希望在函數中改變全局變量的值,應該使用什么關鍵字?
global
1.在嵌套的函數中,如果希望在內部函數修改外部函數的局部變量,應該使用什么關鍵字?
nonlocal
2.python的函數可以嵌套,但是要注意一下訪問的作用域問題哦,請問一下代碼存在什么問題?
def outside(): print('I am outside!') def inside(): print('I am inside!') inside()
解:訪問的作用域問題,inside()是內嵌函數,其作用域(定義、調用)都只能在它的外部函數里面,外面或者別的函數體是不能調用inside()函數的,修改如下:
def outside(): print('I am outside!') def inside(): print('I am inside!') return inside() outside()
3.請問為什么代碼A沒有報錯,但是代碼B卻報錯了?如何修改?
#代碼A def outside(): var = 5 def inside(): var = 3 print(var) inside() outside() #代碼B def outside(): var = 5 def inside(): print(var) var = 3 inside() outside()
因為代碼B中,local variable 'var' referenced before assignment,說的是變量var沒有被定義就拿來使用,所以報錯
outside()函數中有一個var,inside()函數中也有一個var,python為了保護變量的作用域,故將outside()的var變量屏蔽起來,因此此時是無法訪問到外層的var變量的
把上述代碼中的內嵌函數的var = 5(賦值語句)修改為var+=5,就會報錯。因為內嵌函數里面是不能修改非全局變量的外部變量。
4.請問如何訪問funIn()呢?
def funOut(): def funIn(): print('賓果!你成功訪問到我啦!') return funIn()
直接訪問funOut(),因為funOut()里返回的是funIn()函數(即外部函數有對內部函數的調用)
5.請問如何訪問funIn()呢?
def funOut(): def funIn(): print('賓果!你成功訪問到我啦!') return funIn #-----------------------------這里沒有()
這里需要用funOut()()訪問
6.以下是閉包的一個例子,請你目測會打印什么內容?
def funX(): x=5 def funY(): nonlocal x x+=1 return x return funY a=funX() print(a()) print(a()) print(a())
動動手:
0.統計下邊這個長字符串中各個字符出現的次數並找到小甲魚送給大家的一句話
str1 = '拷貝過來的字符串' list1=[] for each in str1: if each not in list1: if each == '\n' print('\\n',str1.count(each)) else: print(each,str1.count(each))
1.請用已經學過的知識編寫程序,找出小甲魚藏在下邊這個長字符串中的密碼,密碼的埋藏點符合以下規律:
a)每位密碼為單個小寫字母
b)每個密碼的左右兩邊均有且只有三個大寫字母
str1='拷貝過來的字符串' countA=0 countB=0 countC=0 length=len(str1) for i in range(length): if str1[i]=='\n': cotinue if str1[i].isupper(): if countB==1: countC +=1 countA=0 else: countA+=1 continue if str1[i].islower() and countA==3: countB=1 countA=0 target=i continue if str1[i].islower() and countC==3: print(str1[target],edn='') countA = 0 countB = 0 countC = 0
2.定義一個斐波那契數的函數
def fibs(num): #斐波那契數列 list1=[0,1] for i in range(num-2):#num個斐波那契數 list1.append(list1[-2] + list1[-1]) return list1 print(fibs(10))