深入理解 Python 中的 global 與 nonlocal 關鍵字

更新日期: 2024 年 11 月 18 日

本文為 python 作用域系列文,第二篇:

在學習 Python 的過程中,變數的作用域是一個重要的概念。

理解如何在不同的作用域中訪問和修改變數,對於寫出高品質的代碼至關重要。

Python 提供了兩個關鍵字——globalnonlocal,用於在函式中明確地聲明變數的作用域。

本文將為新手詳細介紹這兩個關鍵字的用法和注意事項。


什麼是作用域?

作用域(Scope)是指變數在程式中的可見範圍。Python 中的作用域主要分為四種,遵循 LEGB(Local、Enclosing、Global、Built-in) 原則:

  1. Local(本地作用域):函式內部定義的變數。
  2. Enclosing(嵌套作用域):嵌套函式的外部函式作用域。
  3. Global(全域作用域):模組級別,即整個程式範圍內的變數。
  4. Built-in(內建作用域):Python 內建的變數和函式,如 len()

global 關鍵字

用途

global 關鍵字用於在函式內部聲明全域變數。

這意味著在函式內部,你可以對全域變數進行讀取和修改。

基本用法

x = 10  # 全域變數

def modify_global():
    global x
    x = 20  # 修改全域變數
    print(f"函式內部的 x:{x}")

modify_global()
print(f"函式外部的 x:{x}")
# 輸出:
# 函式內部的 x:20
# 函式外部的 x:20

在這個例子中,我們在函式內部使用 global x,從而可以修改全域變數 x

不使用 global 的情況

如果不使用 global 關鍵字,函式內部的同名變數會被視為本地變數,不會影響全域變數。

x = 10

def modify_local():
    x = 20  # 本地變數
    print(f"函式內部的 x:{x}")

modify_local()
print(f"函式外部的 x:{x}")
# 輸出:
# 函式內部的 x:20
# 函式外部的 x:10

nonlocal 關鍵字

用途

nonlocal 關鍵字用於在嵌套函式中聲明非本地且非全域的變數。

這通常用於修改外部函式(但不是全域作用域)中的變數。

基本用法

def outer_function():
    x = 10  # 外部函式的變數

    def inner_function():
        nonlocal x
        x = 20  # 修改外部函式的變數
        print(f"內部函式的 x:{x}")

    inner_function()
    print(f"外部函式的 x:{x}")

outer_function()
# 輸出:
# 內部函式的 x:20
# 外部函式的 x:20

在這個例子中,inner_function 中的 nonlocal x 表示我們要修改外部函式 outer_function 中的變數 x

不使用 nonlocal 的情況

如果不使用 nonlocal 關鍵字,內部函式的同名變數會被視為本地變數,不會影響外部函式的變數。

def outer_function():
    x = 10

    def inner_function():
        x = 20  # 本地變數
        print(f"內部函式的 x:{x}")

    inner_function()
    print(f"外部函式的 x:{x}")

outer_function()
# 輸出:
# 內部函式的 x:20
# 外部函式的 x:10

globalnonlocal 的區別

  • 作用範圍不同
    • global 用於全域作用域,允許在函式內部修改全域變數。
    • nonlocal 用於嵌套函式,允許內部函式修改外部函式的變數。
  • 使用場景不同
    • global 適用於需要在函式內部修改全域變數的情況。
    • nonlocal 適用於需要在嵌套函式中修改外部函式變數的情況。

注意事項

謹慎使用全域變數

過多使用全域變數可能導致代碼難以維護和除錯。

應盡量使用參數傳遞和返回值來避免不必要的全域變數。

nonlocal 的限制

nonlocal 不能用於修改全域變數或本地變數,只能修改嵌套作用域中的變數。

x = 10

def outer_function():
    def inner_function():
        nonlocal x  # 會引發錯誤,因為 x 不在嵌套作用域中
        x = 20

    inner_function()

outer_function()
# 輸出:
# SyntaxError: no binding for nonlocal 'x' found

避免命名衝突

在不同的作用域中使用相同的變數名可能導致混淆。建議使用清晰、具體的變數名。


實際應用

計數器函式

使用 nonlocal 創建一個簡單的計數器函式。

def counter():
    count = 0

    def increment():
        nonlocal count
        count += 1
        return count

    return increment

c = counter()
print(c())  # 輸出:1
print(c())  # 輸出:2
print(c())  # 輸出:3

配置全域設定

使用 global 來修改全域設定,例如日誌級別。

log_level = "INFO"

def set_log_level(level):
    global log_level
    log_level = level

def log(message):
    print(f"[{log_level}] {message}")

set_log_level("DEBUG")
log("這是一條調試訊息")
# 輸出:
# [DEBUG] 這是一條調試訊息

結論

理解 globalnonlocal 關鍵字有助於更靈活地控制變數的作用域。

這對於編寫複雜的程式和構建更健壯的應用程式非常有用。

希望這篇文章能幫助你掌握這兩個關鍵字的用法,並在實際開發中加以應用。


進一步學習

  • 閉包(Closure):深入理解函式如何捕獲外部變數。
  • 裝飾器(Decorator)nonlocal 在裝飾器中的應用。
  • 命名空間(Namespace):更全面地理解變數的存儲和查找方式。

Similar Posts