Python變量作用域

變量作用域是Python編程中非常重要的基礎概念,理解它可以幫助你避免很多常見的錯誤。本文將用簡單易懂的方式,帶你全面掌握Python變量作用域的所有細節。

一、什么是變量作用域?

變量作用域(Scope)指的是變量在程序中的可見范圍,也就是在程序的哪些地方可以訪問這個變量。Python中有4種作用域,按照從內向外的順序分別是:

  1. 局部作用域(Local)?- 在函數內部定義的變量

  2. 嵌套作用域(Enclosing)?- 在嵌套函數的外層函數中定義的變量

  3. 全局作用域(Global)?- 在模塊(文件)頂層定義的變量

  4. 內置作用域(Built-in)?- Python內置的變量(如print、int等)

二、局部作用域(Local Scope)

在函數內部定義的變量屬于局部作用域,只能在函數內部訪問。

def my_function():local_var = "我是局部變量"print(local_var)  # 可以訪問my_function()
print(local_var)  # 報錯:NameError: name 'local_var' is not defined

特點

  • 函數調用時創建,函數結束時銷毀

  • 不同函數中可以定義同名局部變量,互不影響

三、全局作用域(Global Scope)

在函數外部定義的變量屬于全局作用域,可以在整個模塊中訪問。

global_var = "我是全局變量"def func1():print(global_var)  # 可以訪問def func2():print(global_var)  # 可以訪問func1()
func2()
print(global_var)  # 可以訪問

四、global關鍵字

如果要在函數內部修改全局變量,需要使用global關鍵字聲明。

count = 0def increment():global count  # 聲明使用全局變量count += 1increment()
print(count)  # 輸出: 1

如果不使用global:?

count = 0def increment():count = 1  # 這實際上是創建了一個新的局部變量print("函數內:", count)increment()  # 輸出: 函數內: 1
print("函數外:", count)  # 輸出: 函數外: 0

五、嵌套作用域(Enclosing Scope)

在嵌套函數中,外層函數的變量對內層函數可見。

def outer():outer_var = "外層變量"def inner():print(outer_var)  # 可以訪問外層變量inner()outer()

nonlocal關鍵字

如果要修改嵌套作用域中的變量,需要使用nonlocal關鍵字。

def outer():x = 1def inner():nonlocal x  # 聲明使用外層變量x = 2print("inner:", x)inner()print("outer:", x)outer()
"""
輸出:
inner: 2
outer: 2
"""

六、作用域查找規則:LEGB

Python查找變量時按照LEGB規則依次查找:

  1. Local - 局部作用域

  2. Enclosing - 嵌套作用域

  3. Global - 全局作用域

  4. Built-in - 內置作用域

如果都找不到,就會拋出NameError異常。

x = "global"def outer():x = "enclosing"def inner():x = "local"print(x)  # 輸出: localinner()outer()

?變量查找鏈(LEGB):
inner()調用時print(x)的查找過程:
1. 先在inner的局部作用域找 → 找到"local"(停止查找)
? ?↑
2. 如果沒找到,會去outer的作用域找 → "enclosing"
? ?↑
3. 如果還沒找到,會去全局作用域找 → "global"
? ?↑
4. 最后會去內置作用域找

如果刪除inner中的x賦值

修改代碼:

x = "global"def outer():x = "enclosing"def inner():# 刪除了x = "local"print(x)  # 現在會輸出什么?inner()outer()

執行過程:

  1. inner()中print(x)查找x:

    • Local:未找到
      → 向上查找Enclosing作用域(outer的局部作用域)

  2. 找到outer中的x = "enclosing"

    • 輸出: enclosing

七、常見作用域陷阱

1. 在循環/條件語句中沒有獨立作用域

Python中只有函數、類和模塊會創建新的作用域,循環和條件語句不會。

if True:var_in_if = "if中的變量"print(var_in_if)  # 可以訪問,輸出: if中的變量for i in range(1):var_in_for = "for中的變量"print(var_in_for)  # 可以訪問,輸出: for中的變量

2. 列表推導式中的變量泄露

Python 3.x中列表推導式有自己獨立的作用域,但Python 2.x中會泄露到外部作用域。

# Python 3.x
x = "hello"
[print(x) for x in range(3)]
print(x)  # 輸出: hello(x沒有被修改)# Python 2.x中x會被修改為2

3. 默認參數的作用域

默認參數在函數定義時求值,而不是在調用時。

def func(a, lst=[]):  # 默認列表在函數定義時創建lst.append(a)return lstprint(func(1))  # [1]
print(func(2))  # [1, 2] 使用的是同一個列表

具體過程:

  1. 當Python解釋器讀取到函數定義時,它會創建一個空列表對象作為默認參數

  2. 這個列表對象會被綁定到函數的__defaults__屬性中

  3. 每次調用函數時,如果沒有提供lst參數,就會使用這個同一個列表對象

實際執行過程

print(func(1))  # 第一次調用
"""
1. 沒有提供lst參數,使用默認列表(假設內存地址為0x1000)
2. 向這個列表添加1 → [1]
3. 返回這個列表
輸出: [1]
"""print(func(2))  # 第二次調用
"""
1. 仍然沒有提供lst參數,使用同一個默認列表(還是0x1000)
2. 這個列表已經是[1]了,現在添加2 → [1, 2]
3. 返回這個列表
輸出: [1, 2]
"""

為什么這是個問題?

  1. 不符合直覺:大多數人期望每次調用都使用一個新的空列表

  2. 隱藏的共享狀態:函數調用之間意外共享了數據

  3. 難以調試:這種行為不明顯,可能導致難以發現的bug

正確的做法

使用None作為默認值,然后在函數內部創建新列表:

def func(a, lst=None):if lst is None:lst = []lst.append(a)return lst

?現在每次調用都會得到預期行為:

print(func(1))  # [1]
print(func(2))  # [2] 這次是全新的列表

八、閉包和作用域

閉包(Closure)是函數記住并訪問其詞法作用域的能力,即使函數在其原始作用域之外執行。

def outer_func(x):def inner_func(y):return x + y  # inner_func記住了x的值return inner_funcclosure = outer_func(10)
print(closure(5))  # 輸出: 15

九、實際應用建議

  1. 避免過多使用全局變量:會使代碼難以維護和調試

  2. 合理使用函數封裝:將相關代碼和變量組織在函數中

  3. 注意變量命名:避免內外作用域同名變量引起混淆

  4. 使用nonlocal替代全局變量:當需要在嵌套函數中修改外層變量時

十、作用域相關面試題

  1. 下面代碼的輸出是什么?

x = 5def func():print(x)x = 10func()

答案:會報錯,因為在函數中給x賦值,Python會認為x是局部變量,但在print時x還未定義

  1. 如何修改下面的代碼使其正常工作?

total = 0def add_numbers(numbers):for num in numbers:total += numreturn totalprint(add_numbers([1, 2, 3]))

答案:需要在函數內使用global total聲明

總結

理解Python變量作用域是寫出高質量代碼的基礎。記住以下幾點:

  1. 牢記LEGB查找順序

  2. 修改作用域變量需要使用global或nonlocal

  3. 只有函數、類和模塊會創建新作用域

  4. 避免濫用全局變量

  5. 合理使用閉包特性

希望這篇文章能幫助你徹底掌握Python變量作用域!如果有任何問題,歡迎在評論區留言討論。

?

?

?

?

?

?

?

?

?

?

?

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80178.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80178.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80178.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

初學者的AI智能體課程:構建AI智能體的十堂課

初學者的AI智能體課程:構建AI智能體的十堂課 在人工智能(AI)領域,AI智能體正在逐漸發揮其不容忽視的作用。自動化的智能體不僅僅在理論上廣泛討論,更加在實際應用中開辟了一片新的天地。那么如何動手開發屬于自己的AI智能體呢?Microsoft提供的AI智能體入門課正是為此而設…

【并發編程】MySQL鎖及單機鎖實現

目錄 一、MySQL鎖機制 1.1 按鎖粒度劃分 1.2 按鎖功能劃分 1.3 InnoDB鎖實現機制 (1)記錄鎖(Record Lock) (2) 間隙鎖(Gap Lock) (3) 臨鍵鎖(Next-Key Lock) (4) 插入意向鎖(Insert Intention Lock) 二、基于 JVM 本地鎖實現,保證線程安全 2.1 線程不安全的分析 2.1…

能耗優化新引擎:EIOT平臺助力企業降本增效

安科瑞顧強 數字化轉型的背景下,能源管理正加速向智能化、遠程化方向演進。安科瑞電氣推出的EIOT托管平臺及ADW300系列4G無線計量儀表,通過云端技術與無線通信的深度融合,為用戶打造了高效、便捷的遠程能源監測與管理體系,助力企…

(14)Element Plus項目綜合案例

本系列教程目錄:Vue3Element Plus全套學習筆記-目錄大綱 文章目錄 第3章 綜合案例3.1 搭建項目3.1.1 創建Vite工程3.1.2 配置路由 3.2 登錄模塊頁面3.2.1 注冊頁面3.2.2 登錄頁面3.2.3 忘記密碼頁面 3.3 導航設置3.3.1 頭部3.3.2 側邊欄與底部1)頭像部分…

Webug4.0靶場通關筆記22- 第27關文件包含

目錄 一、文件包含 1、原理分析 2、文件包含函數 (1)include( ) (2)include_once( ) (3)require( ) (4)require_once( ) 二、第27關滲透實戰 1、打開靶場 2、源碼分析 3、…

〖 Linux 〗解決 VS Code 遠程連接服務器的常見問題

文章目錄 解決 VS Code 遠程連接服務器的斷開問題VS Code Remote-SSH一直彈出輸入密碼的問題VsCode C 語法檢測失效不標紅色波浪線 解決辦法卸載擴展方式: 解決vscode C智能提示緩慢 解決 VS Code 遠程連接服務器的斷開問題 解決 vscode 卡頓,卡死&…

ERC-20與ERC-721:區塊鏈代幣標準的雙星解析

一、代幣標準的誕生背景 在以太坊生態中,代幣標準是構建去中心化應用(DApps)的基石。ERC-20與ERC-721分別代表同質化與非同質化代幣的兩大核心標準,前者支撐著90%以上的加密資產流通,后者則開啟了數字資產唯一性的新時…

C++入門小館 :多態

嘿,各位技術潮人!好久不見甚是想念。生活就像一場奇妙冒險,而編程就是那把超酷的萬能鑰匙。此刻,陽光灑在鍵盤上,靈感在指尖跳躍,讓我們拋開一切束縛,給平淡日子加點料,注入滿滿的pa…

【NextPilot日志移植】整體功能概要

整體日志系統的實現功能 該日志系統主要實現了飛行日志的記錄功能,支持多種日志記錄模式,可將日志存儲到文件或通過 MAVLink 協議傳輸,同時具備日志加密、空間管理、事件記錄等功能。具體如下: 日志記錄模式:支持按武…

數字化轉型:概念性名詞淺談(第二十五講)

大家好,今天接著介紹數字化轉型的概念性名詞系列。 (1)SOP(標準作業程序) 標準作業程序(Standard Operating Procedure, SOPs)是在有限時間與資源內,為了執行復雜的日常事務所設計的內部程序。從管理學的…

交叉編譯 opencv-4.10

編譯說明 opencv 下包含很多模塊,各個模塊的作用可以參考Opencv—模塊概覽. 嵌入式考慮有限存儲等因素會對模塊進行裁剪,我這里主要保留圖像拼接(stitching)圖片編解碼(imgcodecs)與特征點匹配&#xff08…

Python cv2對象檢測與跟蹤:從基礎到進階實戰

在計算機視覺領域,對象檢測(定位目標位置)與對象跟蹤(持續追蹤目標運動)是視頻分析、自動駕駛、智能監控等應用的核心技術。本文將結合OpenCV的cv2庫,系統講解其原理與Python實現方法。 一、對象檢測 vs 對…

亞馬遜推出新型倉儲機器人 Vulcan:具備“觸覺”但不會取代人類工人

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎?訂閱我們的簡報,深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同,從行業內部的深度分析和實用指南中受益。不要錯過這個機會,成為AI領…

緩存套餐-03.功能測試

一.功能測試 點擊小程序,就會觸發根據分類id查詢套餐方法,根據分類id查詢套餐。 第一次查詢,redis中沒有數據,就會發sql進行sql數據庫查詢。 redis當中就有了對應的緩存。 再次點擊,發現sql根本沒有執行,…

WebFlux與HttpStreamable關系解析

1-Streamable 1-WebFlux與HttpStreamable關系解析2-MCP協議Streamable HTTP 2-參考網址 MCP協議Streamable HTTPMCP協議重大升級,Spring AI Alibaba聯合Higress發布業界首個Streamable HTTP實現方案 3-WebFlux與HttpStreamable關系解析 WebFlux 和 HttpStreamabl…

順豐科技:從 Presto 到 Doris 湖倉構架升級,提速 3 倍,降本 48%

導讀:順豐科技引入 Doris 替換 Presto,在內部可視化數據自助分析工具豐景臺場景廣泛應用。目前,順豐臨時查詢業務、豐景臺報表業務的 Presto 場景已經 100% 切換到 Doris 集群中,日均查詢量 100W。并實現 P95 性能提升近 3 倍&…

如何在Jmeter中調用C程序?

在JMeter中調用C語言程序可以通過以下幾種方式實現: 方法一:使用OS Process Sampler JMeter的“OS Process Sampler”可以用來調用外部程序,包括C語言編寫的可執行文件。 步驟: 準備C語言程序: 編寫C語言代碼并編譯…

python 中的單例

在 Python 里,單例模式指的是一個類僅有一個實例,并且提供一個全局訪問點來獲取該實例。下面為你介紹幾種實現單例模式的常見方法。 1. 使用模塊 在 Python 里,模塊天然就是單例模式。當模塊被導入時,Python 會對其進行一次加載…

Linux58 ssh服務配置 jumpserver 測試雙網卡 為何不能ping通ip地址

判斷為NAT模式網卡 能ping 通外網 ens34為僅主機模式網卡 [rootlocalhost network-scripts]# ip route show default default via 10.1.1.254 dev ens33 proto static metric 100 10.0.0.0/8 dev ens33 proto kernel scope link src 10.1.1.37 metric 100 11.0.0.0/8 dev…

web 自動化之 selenium+webdriver 環境搭建及原理講解

文章目錄 一、web 自動化測試學習說明二、什么 web 自動化測試三、selenium 簡介四、web自動化測試環境搭建五、web 自動化測試第一個腳本六、selenium 原理及源碼講解 一、web 自動化測試學習說明 進階 web 自動化測試學習:掌握 python 編程基礎 二、什么 web 自…