Python中全局變量和局部變量的區(qū)別以及使用
0. 前置知識
0.1 作用域
所謂作用域(Scope),就是變量的有效范圍,就是變量可以在哪個范圍以內(nèi)使用。
- 有些變量可以在整段代碼的任意位置使用
- 有些變量只能在函數(shù)內(nèi)部使用
- 有些變量只能在 for 循環(huán)內(nèi)部使用
變量的作用域由變量的定義位置決定,在不同位置定義的變量,它的作用域是不一樣的。在Python語言中,變量一般根據(jù)作用域被劃分為兩種:
- 局部變量
- 全局變量。
1. 局部變量
定義:在函數(shù)內(nèi)部定義的變量,它的作用域也僅限于函數(shù)內(nèi)部,出了函數(shù)就不能使用了,我們將這樣的變量稱為局部變量(Local Variable)。
理論:要知道,當函數(shù)被執(zhí)行時,Python 會為其分配一塊臨時的存儲空間,所有在函數(shù)內(nèi)部定義的變量,都會存儲在這塊空間中。而在函數(shù)執(zhí)行完畢后,這塊臨時存儲空間隨即會被釋放并回收,該空間中存儲的變量自然也就無法再被使用。
例子1:
>>> def demo(): ... text = "在函數(shù)內(nèi)部聲明了一個變量,這個變量就是局部變量" ... print(text) ... >>> demo() 在函數(shù)內(nèi)部聲明了一個變量,這個變量就是局部變量 >>> print(text) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'text' is not defined
在上面的例子中,text變量的聲明(創(chuàng)建)是在函數(shù)demo中,所以它是一個局部變量,所以在函數(shù)外面是不可以直接使用的。
如果試圖在函數(shù)外部訪問其內(nèi)部定義的變量,Python 解釋器會報 NameError 錯誤,并提示我們沒有定義要訪問的變量,這也證實了當函數(shù)執(zhí)行完畢后,其內(nèi)部定義的變量會被銷毀并回收。
1.1 問題一:同名變量
我們思考一個問題,如果在函數(shù)外部和函數(shù)內(nèi)部都定義了同名變量,那么會怎么樣呢?
>>> def demo(): ... text = "在函數(shù)內(nèi)部聲明了一個變量,這個變量就是局部變量" ... print(text) ... >>> text = "在函數(shù)外部創(chuàng)建了同名變量" >>> demo() 在函數(shù)內(nèi)部聲明了一個變量,這個變量就是局部變量 >>> print(text) 在函數(shù)外部創(chuàng)建了同名變量
很明顯,因為在函數(shù)外部定義了text變量,所以外部在調(diào)用text時不會調(diào)用函數(shù)內(nèi)部的text而是調(diào)用前面我們定義的text。
1.2 問題二:函數(shù)調(diào)用函數(shù)外的變量
那函數(shù)可以直接調(diào)用函數(shù)外的變量嗎?
>>> def demo():
... print(f"函數(shù)直接調(diào)用外部變量 [{text}]")
...
>>> text = "在函數(shù)外部創(chuàng)建的變量"
>>> demo()
函數(shù)直接調(diào)用外部變量 [在函數(shù)外部創(chuàng)建的變量]
可以看到,函數(shù)在直接定義時是可以調(diào)用外部變量的,且不會報錯。當我們調(diào)用函數(shù)時,只要保證其調(diào)用的外部變量存在,則不會報錯,否則就會報錯。下面是報錯的情況:
>>> def demo():
... print(f"直接調(diào)用main中的變量: {text}")
...
>>> # 此時main函數(shù)中并沒有text變量
>>> demo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in demo
NameError: name 'text' is not defined
2. 全局變量
除了在函數(shù)內(nèi)部定義變量,Python 還允許在所有函數(shù)的外部定義變量,這樣的變量稱為全局變量(Global Variable)。
和局部變量不同,全局變量的默認作用域是整個程序,即全局變量既可以在各個函數(shù)的外部使用,也可以在各函數(shù)內(nèi)部使用。
定義全局變量的方式有以下 2 種:
- 在main函數(shù)中定義的變量
- 在函數(shù)體內(nèi)聲明的全局變量
2.1 第一種聲明方式 —— 在main函數(shù)中定義的變量
其實我們在問題1.1和問題1.2中已經(jīng)寫了,在函數(shù)體外定義的變量其實就是全局變量,也就是在main函數(shù)中定義的變量就是全局變量。
舉個例子:
>>> global_var_1 = "這是一個全局變量"
>>> global_var_2 = ["這也是一個全局變量", 123]
>>> # 再定義一個函數(shù)和局部變量
>>> def demo(local_var_1, local_var_2):
... local_var_3 = "這是一個局部變量"
... local_var_4 = ("這也是一個局部變量", 456)
... print(local_var_1)
... print(local_var_2)
... print(local_var_3)
... print(local_var_4)
... print("局部變量打印完畢")
...
>>> demo(1, 2) # 這里傳給函數(shù)的兩個形參是全局變量
1
2
這是一個局部變量
('這也是一個局部變量', 456)
局部變量打印完畢
>>> global_var_1
'這是一個全局變量'
>>> global_var_2
['這也是一個全局變量', 123]
2.2 第二種聲明方式 —— 在函數(shù)體內(nèi)聲明的全局變量
在函數(shù)體內(nèi)也是可以創(chuàng)建全局變量的,步驟如下:
def 函數(shù)名稱(形參1, 形參2, ...): # 1. 需在變量前使用關鍵字`global`進行聲明,這樣一個全局變量就創(chuàng)建好了 gloabl 全局變量名 # 2. 聲明完畢后賦值 全局變量名 = 值 # 3. 在調(diào)用函數(shù)之后,在函數(shù)中聲明的全局變量也就被創(chuàng)建了,否則不會創(chuàng)建的 函數(shù)名稱(傳參1,傳參2) # 4. 可以任意使用那個全局變量了 print(全局變量)
2.2.1 正確
>>> def demo():
... # 聲明一個局部變量var_1
... var_1 = "This is a local variable"
... # 1. 先用global關鍵詞進行全局變量的聲明
... global var_2
... # 2. 再對全局變量進行賦值
... var_2 = "This is a global variable"
... print(f"[在函數(shù)內(nèi)使用] local_var: {var_1}")
... print(f"[在函數(shù)內(nèi)使用] global_var: {var_2}")
...
>>> demo()
[在函數(shù)內(nèi)使用] local_var: This is a local variable
[在函數(shù)內(nèi)使用] global_var: This is a global variable
>>> # 在main函數(shù)中調(diào)用函數(shù)生成的全局變量
>>> print(f"[在main函數(shù)中使用] global_var: {var_2}")
[在main函數(shù)中使用] global_var: This is a global variable
2.2.2 錯誤1 —— 沒有調(diào)用函數(shù)就使用函數(shù)內(nèi)部將會創(chuàng)建的全局變量
如果不調(diào)用函數(shù)就直接使用函數(shù)中創(chuàng)建的全局變量,是會報錯的,如下:
>>> def demo():
... # 創(chuàng)建一個局部變量
... var_1 = "局部變量123"
... # 1. 先聲明是全局變量
... global var_2
... # 2. 再進行賦值操作
... var_2 = "全局變量456"
...
>>> # 如果不調(diào)用函數(shù)直接使用在函數(shù)中生成的全局變量
>>> print(f"var_2: {var_2}")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'var_2' is not defined
>>> # 必須先調(diào)用函數(shù)后,函數(shù)中的全局變量才能生成
>>> demo()
>>> print(f"var_2: {var_2}")
var_2: 全局變量456
2.2.3 錯誤2 —— 使用global關鍵字聲明全局變量時直接對其進行賦值
>>> def demo():
... # 如果聲明時直接賦值
... global var_1 = "這是一個全局變量,但是在聲明時就賦值了"
File "<stdin>", line 3
global var_1 = "這是一個全局變量,但是在聲明時就賦值了"
^
SyntaxError: invalid syntax
2.2.4 思考 —— 多個函數(shù)對同一變量進行全局變量聲明會報錯嗎?
看例子,很容易:
>>> def func_1():
... global var_1
... var_1 = "abc"
... print(f"[function_1]全局變量var_1已經(jīng)創(chuàng)建: {var_1}")
...
>>> def func_2():
... global var_1
... var_1 = "123"
... print(f"[function_2]全局變量var_1已經(jīng)創(chuàng)建: {var_1}")
...
>>> # 其實沒什么影響,和賦值的原理是一樣的
>>> # 先調(diào)用func_1
>>> func_1()
[function_1]全局變量var_1已經(jīng)創(chuàng)建: abc
>>> var_1
'abc'
>>> # 再調(diào)用func_2
>>> func_2()
[function_2]全局變量var_1已經(jīng)創(chuàng)建: 123
>>> var_1
'123'
3. 獲取指定作用域范圍中的變量
在一些特定場景中,我們可能需要獲取某個作用域內(nèi)(全局范圍內(nèi)或者局部范圍內(nèi))所有的變量,Python 提供了以下 3 種方式:
globals()函數(shù)locals()函數(shù)vars(object)函數(shù)
3.1globals()函數(shù)
globals()函數(shù)為 Python 的內(nèi)置函數(shù),它可以返回一個包含全局范圍內(nèi)所有變量的字典,該字典中的每個鍵值對,鍵為變量名,值為該變量的值。
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'demo': <function demo at 0x7ff433a520d0>, 'var_2': '全局變量456', 'func_1': <function func_1 at 0x7ff433a52280>, 'func_2': <function func_2 at 0x7ff433a52160>, 'var_1': '123'}
注意,globals()函數(shù)返回的字典中,會默認包含有很多變量,這些都是 Python 主程序內(nèi)置的,不用理會它們。
可以看到,通過調(diào)用 globals() 函數(shù),我們可以得到一個包含所有全局變量的字典。并且,通過該字典,我們還可以訪問指定變量,甚至如果需要,還可以修改它的值。例如,在上面程序的基礎上,添加如下語句:
>>> print(globals()["var_2"])
全局變量456
>>> globals()["var_2"] = "對這個全局變量進行重新賦值!"
>>> print(globals()["var_2"])
對這個全局變量進行重新賦值!
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'demo': <function demo at 0x7ff433a520d0>, 'var_2': '對這個全局變量進行重新賦值!', 'func_1': <function func_1 at 0x7ff433a52280>, 'func_2': <function func_2 at 0x7ff433a52160>, 'var_1': '123'}
3.2locals()函數(shù)
locals() 函數(shù)也是 Python 內(nèi)置函數(shù)之一,通過調(diào)用該函數(shù),我們可以得到一個包含當前作用域內(nèi)所有變量的字典。這里所謂的“當前作用域”指的是:
- 在函數(shù)內(nèi)部調(diào)用
locals()函數(shù),會獲得包含所有局部變量的字典 - 而在全局范文內(nèi)調(diào)用
locals()函數(shù),其功能和globals()函數(shù)相同。
>>> def demo(a, b):
... c = 10 # 定義局部變量
... global d # 聲明全局變量
... d = 100
... print(locals()) # 查看該函數(shù)的局部變量
... return a + b + c + d
...
>>> # 定義一些全局變量
>>> aaa = 123
>>> bbb = 456
>>> # 查看全局變量
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'demo': <function demo at 0x7f1132cbd0d0>, 'aaa': 123, 'bbb': 456}
>>> # 查看局部變量
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'demo': <function demo at 0x7f1132cbd0d0>, 'aaa': 123, 'bbb': 456}
>>> # 調(diào)用函數(shù)
>>> demo(1, 2)
{'a': 1, 'b': 2, 'c': 10}
113
>>> # 查看全局變量
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'demo': <function demo at 0x7f1132cbd0d0>, 'aaa': 123, 'bbb': 456, 'd': 100}
>>> # 查看局部變量
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'demo': <function demo at 0x7f1132cbd0d0>, 'aaa': 123, 'bbb': 456, 'd': 100}
Note:
- 當使用 locals() 函數(shù)獲得所有局部變量組成的字典時,可以向 globals() 函數(shù)那樣,通過指定鍵訪問對應的變量值,但無法對變量值做修改。
3.3var(object)函數(shù)
vars() 函數(shù)也是 Python 內(nèi)置函數(shù),其功能是返回一個指定 object 對象范圍內(nèi)所有變量組成的字典。如果不傳入object 參數(shù),vars() 和 locals() 的作用完全相同。
>>> class A:
... def __init__(self, a, b, c):
... self.a = a
... self.b = b
... self.c = c
... name = "Leovin"
... school = "xxx University"
...
>>> print(f"vars(A): {vars(A)}")
vars(A): {'__module__': '__main__', '__init__': <function A.__init__ at 0x7fd201d5e160>, 'name': 'Leovin', 'school': 'xxx University', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
>>> print(vars())
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'A': <class '__main__.A'>}
>>> print(globals())
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'A': <class '__main__.A'>}
>>> print(locals())
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'A': <class '__main__.A'>}
>>> def func(a, b):
... c = 1
... global d
... d = 10
... return a + b + c + d
...
>>> vars(func)
{}
>>> vars(func(1, 2))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: vars() argument must have __dict__ attribute
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'A': <class '__main__.A'>, 'func': <function func at 0x7fd201d5e0d0>, 'd': 10}
>>> vars(A)
mappingproxy({'__module__': '__main__', '__init__': <function A.__init__ at 0x7fd201d5e160>, 'name': 'Leovin', 'school': 'xxx University', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None})
到此這篇關于Python中全局變量和局部變量的區(qū)別以及使用的文章就介紹到這了,更多相關Python 全局變量和局部變量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python數(shù)據(jù)結(jié)構(gòu)之二叉樹的建立實例
這篇文章主要介紹了python數(shù)據(jù)結(jié)構(gòu)之二叉樹的建立實例,采用了類似遞歸方式建立,需要的朋友可以參考下2014-04-04
Python使用pdf2image實現(xiàn)PDF轉(zhuǎn)圖片的完整指南
pdf2image 是一個用于將 PDF 文件轉(zhuǎn)換為圖像的 Python 庫,它基于強大的 poppler-utils 工具集,提供簡單高效的 PDF 到圖像的轉(zhuǎn)換功能,本文給大家介紹了Python使用pdf2image實現(xiàn)PDF轉(zhuǎn)圖片的完整指南,需要的朋友可以參考下2025-11-11
使用Python的Tornado框架實現(xiàn)一個Web端圖書展示頁面
Tornado是Python的一款高人氣Web開發(fā)框架,這里我們來展示使用Python的Tornado框架實現(xiàn)一個Web端圖書展示頁面的實例,通過該實例可以清楚地學習到Tornado的模板使用及整個Web程序的執(zhí)行流程.2016-07-07
Python如何把十進制數(shù)轉(zhuǎn)換成ip地址
這篇文章主要介紹了Python如何把十進制數(shù)轉(zhuǎn)換成ip地址,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-05-05
Python統(tǒng)計python文件中代碼,注釋及空白對應的行數(shù)示例【測試可用】
這篇文章主要介紹了Python統(tǒng)計python文件中代碼,注釋及空白對應的行數(shù),涉及Python針對py文件的讀取、遍歷、判斷、統(tǒng)計等相關操作技巧,需要的朋友可以參考下2018-07-07

