不間斷 Python 挑戰 Day 17 - 變數範圍 (Scope)

不間斷 Python 挑戰 Day 17 - 變數範圍 (Scope)

更新於 發佈於 閱讀時間約 8 分鐘

Python依據變數有效的範圍可以區分為全域變數(Global variable)或區域變數(Local variable)。在函數內宣告的變數為區域變數,有效範圍只有在函數內,函數外部無法引用這個變數;在函數以外宣告的變數為全域變數,它的有效範圍為整個檔案,並且在函數內部也可以引用這個變數。

全域變數

在函數外部宣告的變數為全域變數,可在函數內部與外部被引用,如下範例,函數內部和外部可以印出同樣的訊息。

global_message = "This is global message."

def print_global_message():
  print("In function:", global_message)

print_global_message()
print("In main:", global_message)

執行結果:

In function: This is a global message.
In main: This is a global message.

函數內修改全域變數

若嘗試在函數內修改全域變數,實際上並不會修改到該全域變數,而僅是在函數內新增了一個區域變數。

global_message = "This is global message."

def modify_global_message():
  global_message = "Modify global message"
  print("In function:", global_message)

modify_global_message()
print("In main:", global_message)

執行結果:

In function: Modify global message.
In main: This is a global message.

若要在函數中修改全域變數,我們可以使用global關鍵字,來宣告這個變數是一個全域變數。

def modify_global_message():
  global global_message
  global_message = "Modify global message"
  print("In function:", global_message)

modify_global_message()
print("In main:", global_message)

如此一來,函數內外就可以印出一樣的結果。

In function: Modify global message.
In main: Modify global message.

區域變數

在函數內部宣告的變數為區域變數,只能在函數內部被引用,若試圖在函數外部引用該變數會產生錯誤。

def define_local_message():
  local_message = "This is a local message."

define_local_message()
print(local_message)

執行結果出現錯誤:

NameError: name 'local_message' is not defined.

函數內修改上一層函數的變數

若函數內部還有定義函數,嘗試在內層函數修改外層函數的變數,實際上並不會修改到該變數,只是在內層函數中又新增了一個區域變數。

def print_local_message():
  local_message = "This is a local message"
  def modify_outer_message():
    local_message = "Modify local message."
    print("Inner function:", local_message)
  modify_outer_message()
  print("Outer function:", local_message)

print_local_message()

執行結果:

Inner function: Modify local message.
Outer function: This is a local message.

在此情境下,可以使用nonlocal關鍵字,來宣告這個變數是上一層函數的區域變數。

def print_local_message():
  local_message = "This is a local message."
  def modify_outer_message():
    nonlocal local_message
    local_message = "Modify local message."
    print("Inner function:", local_message)
  modify_outer_message()
  print("Outer function:", local_message)

print_local_message()

執行結果:

Inner function: Modify local message.
Outer function: Modify local message.

查詢全域變數與區域變數

我們可以透過Python內建的函數globals()locals()來查詢所有的全域變數和區域變數。

def local_variables():
  local_var_a = 1
  local_var_b = 2
  print("Local variables:", locals())

global_var_a = 1
global_var_b = 2
local_variables()
print("Global variables:", globals())

執行結果:

Local variables: {'local_var_a': 1, 'local_var_b': 2}
Global variables: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000235D4221510>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\wjweng\\PycharmProjects\\marathon_python\\main.py', '__cached__': None, 'local_variables': <function local_variables at 0x00000235D3DA3E20>, 'global_var_a': 1, 'global_var_b': 2}

程式範例

https://github.com/wjweng/marathon_python/blob/master/Day1_to_25/marathon_python_day17.py


avatar-img
Wei-Jie Weng的沙龍
47會員
36內容數
留言
avatar-img
留言分享你的想法!
Wei-Jie Weng的沙龍 的其他內容
這篇文章將利用之前所學過的一些東西,包括if敘述、串列、while迴圈、函數等等的觀念,來實作一個撲克牌的小遊戲-21點。
在前面的文章中我們學習了關於字典的基本用法,今天再討論更多關於字典的其它用法,以及它和串列、元組等的關聯。
在程式設計中,我們會使用到一些固定不會變動的資料內容,例如一年的月份、物體的邊長、過去一周的氣溫等等,使用串列的結構固然也可以用來儲存這些資料,但串列可以被新增或刪除,不能有效保護這類不可變動的資料。因此,Python也提供了另一種形式的資料結構,稱為元組,它的資料結構和串列相同,但資料的內容不可變
當我們查字典時,會先找到想查詢的單字在字典裡的位置,才能在那個位置找到單字的定義;在Python中,也有一個類似的資料結構稱作字典,字典的鍵(key)就對應到我們要查詢的單字,字典的值(value)則是該單字的定義。
隨著程式的功能愈來愈複雜,程式碼也愈來愈多,若程式從頭寫到尾沒有任何的段落,可讀性會愈來愈差,甚至會發現同樣的一段程式碼重覆很多遍,因為類似的功能區塊在程式中可能會一再出現。這樣的程式碼不利於多人的協作開發,即使是寫作者本身在一段時間後回來看,可能也難以一眼就掌握程式的主要架構。
另一種迴圈的形式是while迴圈,和for迴圈常常可以達到相同的功能,差別在於for迴圈是在一定的範圍內迭代,例如從1到100,或是串列裡的每一個元素;而while迴圈是一個條件判斷的迴圈,當滿足這個條件就執行迴圈的內容,不滿足時就跳出迴圈。
這篇文章將利用之前所學過的一些東西,包括if敘述、串列、while迴圈、函數等等的觀念,來實作一個撲克牌的小遊戲-21點。
在前面的文章中我們學習了關於字典的基本用法,今天再討論更多關於字典的其它用法,以及它和串列、元組等的關聯。
在程式設計中,我們會使用到一些固定不會變動的資料內容,例如一年的月份、物體的邊長、過去一周的氣溫等等,使用串列的結構固然也可以用來儲存這些資料,但串列可以被新增或刪除,不能有效保護這類不可變動的資料。因此,Python也提供了另一種形式的資料結構,稱為元組,它的資料結構和串列相同,但資料的內容不可變
當我們查字典時,會先找到想查詢的單字在字典裡的位置,才能在那個位置找到單字的定義;在Python中,也有一個類似的資料結構稱作字典,字典的鍵(key)就對應到我們要查詢的單字,字典的值(value)則是該單字的定義。
隨著程式的功能愈來愈複雜,程式碼也愈來愈多,若程式從頭寫到尾沒有任何的段落,可讀性會愈來愈差,甚至會發現同樣的一段程式碼重覆很多遍,因為類似的功能區塊在程式中可能會一再出現。這樣的程式碼不利於多人的協作開發,即使是寫作者本身在一段時間後回來看,可能也難以一眼就掌握程式的主要架構。
另一種迴圈的形式是while迴圈,和for迴圈常常可以達到相同的功能,差別在於for迴圈是在一定的範圍內迭代,例如從1到100,或是串列裡的每一個元素;而while迴圈是一個條件判斷的迴圈,當滿足這個條件就執行迴圈的內容,不滿足時就跳出迴圈。