Python 函式和變數作用域

Python探索牛發表於2024-04-23

變數引用順序

Python 引用變數的順序:當前作用域區域性變數->外層作用域變數->當前模組中的全域性變數->Python內建變數。

1、 global

global 關鍵字用來在函式或其他區域性作用域中使用全域性變數,如果不對全域性變數進行修改,那麼可以不使用global關鍵字;如果想要在函式或區域性作用域中對全域性變數進行修改操作,那麼必須在函式或區域性作用域中使用global關鍵字進行宣告,否則報錯:UnboundLocalError

count = 1
def foo():
  global count  #如果不加這個那麼就會報錯
  count += 1
  print(count)
foo()

2、 nonlocal

使用情況:閉包,巢狀函式中

如果內部函式想要對外部函式的區域性變數進行修改時,需要在內部函式中宣告:

nonlocal <變數名>

nonlocal語句會搜尋當前呼叫棧中的下一層函式的定義。

def a():
  count = 1
  def b():
    nonlocal count
    count += 1
    print(count)
  return b
a()()

  

3、 裝飾器

介紹:裝飾器的作用是將被修飾的函式當作引數傳遞給與裝飾器對應的函式,並返回包裝後的被裝飾的函式。裝飾器其實是閉包的一種特殊情況

 def a(func):
  return func
 
@a
def b():
  pass
b()

  

執行示意圖:
在這裡插入圖片描述
解析過程:

發現@a,那麼就將會執行a(b),返回b
b(),這一步呼叫的其實是a返回的同一名的b函式,並且開始執行b函式中的操作

4、 閉包

閉包概念:在電腦科學中,閉包(Closure)是詞法閉包的簡稱,是引用了自由變數的函式,這個被引用的自由變數將和這個函式一同存在,即使已經離開了創造它的環境也不例外。

簡單介紹:可以理解為一個封閉的包裹,這個包裹就是一個函式和函式內部對應的邏輯,包裹裡面的東西就是自由變數,自由變數可以隨著包裹到處遊蕩,比如:裝飾器是一個閉包,隨著裝飾器進行傳遞的函式名就是自由變數(函式),裝飾器和內部邏輯結構就是閉包中的函式和內部邏輯。

def func(name):
  def inner_func(age):
    print(‘name:’+name+’ age:’+age)
  return inner_func
 
a = func(‘liyang’)
a(20)   #>>> name:liyang age:20

  

上面的例子中:呼叫func函式時就產生了閉包inner_func,該閉包所持有的自由變數是name。

當函式func的生命週期結束之後,name這個變數依然存在,因為它被閉包引用了,所以不會被回收。

5、 延遲繫結

Python函式的作用域是由程式碼決定的,也就是靜態的,但是使用是動態的,是在執行時確定的

閉包中遇到的問題

fs = [lambda x: x*I for i in range(4)]
print(fs[0](1))     #>>> 3

期望輸出結果是:0,但是結果卻是:3

這是因為只有在函式foo被執行的時候才會搜尋變數i的值,由於迴圈已結束,i指向最終值3,所以最終會發現結果都是一樣。

使用下面的閉包方式,就會得到期望的結果:

def foo(i):
  return lambad x: x*i
#學習中遇到問題沒人解答?小編建立了一個Python學習交流群:153708845 
fs = [foo(i) for i in range(4)]
print(fs[0](1))

相關文章