簡體   English   中英

Python function 內的全局關鍵字可見性

[英]Python global keyword visibility inside function

當我錯誤地運行 CODE1 時,我正在檢查項目的全局關鍵字是如何工作的,它的工作方式出乎我的意料。 global 關鍵字在 function 中生效,即使它不在執行部分中(即在 if which 條件不成立)。

我一直在尋找有關 python 中 global 關鍵字的問題,但我找不到對此的回應。 我看到: Python 全局關鍵字行為,python 中的全局關鍵字, 在 function使用全局變量

最有趣的,我認為它可能與它有關的是這個(但我不確定): Python 全局關鍵字

下面顯示了我使用的代碼的三個最小可重現示例:

CODE1(帶全局關鍵字):

a = 0
def my_function():
    b=2
    if b==0:
        print("first if")
        global a
    if b==2:
        print("second if")
        a = 2
        print("func -> a", a)
        print("func -> b", b)

if __name__ == '__main__':
    my_function()
    print("main -> a", a)

結果:

second if
func -> a 2
func -> b 2
main -> a 2

CODE2(無全局關鍵字):

a = 0
def my_function():
    b=2
    if b==0:
        print("first if")
    if b==2:
        print("second if")
        a = 2
        print("func -> a", a)
        print("func -> b", b)

if __name__ == '__main__':
    my_function()
    print("main -> a", a)

結果:

second if
func -> a 2
func -> b 2
main -> a 0

CODE3(使用 global 關鍵字,但反向 if 語句):

a = 0
def my_function():
    b=2
    if b==2:
        print("second if")
        a = 2
        print("func -> a", a)
        print("func -> b", b)
    if b==0:
        print("first if")
        global a

if __name__ == '__main__':
    my_function()
    print("main -> a", a)

結果:

  File "global_var_test.py", line 18
    global a
    ^
SyntaxError: name 'a' is used prior to global declaration

可以看出, if b==0:始終為 False, if b==2:始終為 True(打印確認)。 我希望 CODE1 給出與 CODE2 相同的結果,因為global a在第一個示例中不會被執行,所以它與省略它相同。 但它給出了一個不合邏輯的結果,其中 global 關鍵字無論如何都會生效,並且全局變量 a 更改為值 2。在此之后,我使用 CODE3 進行測試,認為 global 關鍵字將在所有 function 中可見,而不管其 position 和那么 CODE3 應該給出與 CODE1 相同的結果。 我又錯了,它的工作方式就像global a將被執行(然后它是在分配之后並引發異常)。

然后,我的最后一個問題是: ¿ global 關鍵字(可能還有其他關鍵字,如 nonlocal 等)在代碼中是否按編寫順序可見,但與正在執行的內容無關?

請幫助我澄清這一點。

對這個問題的回答可能有助於理解這里的一些技術細節,盡管這是一個略有不同的問題。

簡而言之,正如您所發現的,Python 編譯器將基本上根據變量在 function 中的使用方式來確定變量的 scope; 這與控制語句之類的細節無關,因此如果在看到global語句之前碰巧遇到了a = 2之類的賦值,它將確定a是局部變量。 如果您嘗試反轉代碼(您沒有給出非常像這樣的示例),以便編譯器碰巧首先看到global語句,它將起作用(盡管仍然是錯誤的代碼):

a = 0
def my_function():
    b=2
    if b==2:
        print("second if")
        global a
        print("func -> a", a)
        print("func -> b", b)
    if b==0:
        print("first if")
        a = 2

因此,出於實用/技術以及風格目的,您應該始終在 function 的開頭聲明global (或nonlocal )變量,而不是其他任何地方。

我不確定這是語言要求還是 CPython 的細節; 這將是一個有趣的后續問題。

更新:是的,這是語言規范要求; https://docs.python.org/3/reference/simple_stmts.html#grammar-token-global-stmt

全局語句中列出的名稱不得在該global語句之前的同一代碼塊中使用。

這里的文本前面只是指代碼的文本,而不考慮控制語句等周圍的細節。 這是因為global實際上是parser的指令,它根據變量第一次看到使用的變量的方式來確定變量是否具有局部或全局綁定。 盡管在實現細節方面可能仍然不完全准確; 例如,CPython 為代碼模塊構建一個符號表,作為對從解析器返回的 AST 的單獨傳遞。 因此,代碼的文本順序也會影響 AST 中節點的遍歷順序。 例如,您可以在global語句的訪問者中查看錯誤消息的來源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM