網站首頁 編程語言 正文
一、命名空間和作用域
當出現了函數,變量聲明的位置就發生了變化,不同位置聲明的變量,能訪問這個變量的范圍也出現了限制
1.1 定義
**命名空間:**聲明定義了變量,變量存在的范圍,主要是通過命名空間,來區分不同范圍中聲明的變量。作用域: 一個數據能夠作用的范圍
命名空間根據范圍的不同,分為以下幾種類型:
1.2 內建命名空間和內建作用域
Python程序中最大的一個命名空間,通常在解釋器運行目標代碼的時候(也就是點RUN的時候),由解釋器創建的一個命名空間,負責初始化(即第一次賦值、第一次創建)系統環境變量。如:int/type()等
- 內建命名空間加載時間:運行代碼之前,通過解釋器加載好系統的命名空間。包含了int/float/str/type()等等各種數據類型或者函數,所以我們在代碼中才可以直接使用這些數據類型或者函數
- 作用:初始化系統環境變量
- 作用域:內建作用域(Builtin),此空間內的數據作用范圍是整個內建空間,包括子空間
- 查看方式:dir()
1.3 全局命名空間和全局作用域
定義: 編寫Python代碼時,創建一個python文件,其中聲明在函數外部的變量,稱為:全局變量(global)。當前可以聲明全局變量的所有位置稱為全局命名空間
加載時間:解釋器運行目標代碼時,加載全局命名空間,初始化該命名空間中的所有全局變量作用:聲明、定義全局變量的范圍作用域:全局作用(Global)查看方式:globals()查看當前全局命名空間中的所有全局變量,本質上globals()就是一個存儲了數據的字典,
例如:
name = "張三"
age = 12
grade = ["1",2,"3"]
def outer():
a = "a"
def inner():
a = "b"
return inner
fun = outer()
fun()
print(f"全局變量字典為:{globals()}")
運行結果:
1.3 局部命名空間和局部作用域
定義:當Python文件中聲明函數時,獨立出來了一個小的作用范圍(函數內部),通常情況下我們將函數內部的空間稱為:局部命名空間
加載時間:解釋器運行目標代碼時,加載完全局命名空間之后,加載局部命名空間,初始化局部命名空間中的局部變量
注意:如果是嵌套函數,嵌套函數是沒有命名空間的,嵌套函數的空間存于父函數內,但嵌套函數是有其自己的作用域的,叫嵌套作用域(內部作用域)
作用:聲明、定義局部變量作用域:局部作用域(嵌套作用域)查看方式:Locals()查看當前命名空間中的所有數據
Locals(): 查看當前命名空間中的數據
編寫在函數內部:查看局部命名空間中的數據編寫在函數外部:和globals()一樣的意義
示例:
name = "張三"
age = 12
grade = ["1",2,"3"]
def outer():
a = "a"
print(f"outer局部的數據:{locals()}")
def inner():
a = "b"
print(f"inner局部的數據:{locals()}")
return inner
fun = outer()
fun()
print(f"全局變量字典為:{globals()}")
print(f"全局部的數據:{locals()}")
運行結果:
1.4 總結
- 命名空間是一個名詞, 表示了一個可以聲明變量的范圍
- 用作域是一個動詞,表示一個變量起作用的范圍
- 解釋器運行時,命名空間的加載順序:內建命名空間–>全局命名空間–>局部命名空間
- 查詢使用變量,查詢使用順序:內部作用域–>嵌套作用域–>全局作用域–>內建作用域,也就是Python常說的LEGB原則。查找順序通俗的說就是:就近原則,一直找到內建作用域,找不到報:“name is not defined”
1.5 擴展LEGB
- Local,本地作用域,局部作用域的local命名空間。函數調用時創建,調用結束消亡
- Enclosing,Python2.2時引入嵌套函數,實現了閉包,這個就是嵌套函數的外部函數的命名空間
- Global,全局作用域,即一個模塊的命名空間。模塊被import時創建 ,解釋器退出時消亡
- Build-in,內置模塊的命名空間,生命周期從python解釋器啟動時創建到解釋器退出時消亡,例如:print(open),print和open都是的變量
二、Global關鍵字的使用說明
在講述什么是Global之前,讓我們先來看一個例子,以下例子兩條print語句分別打印什么:
x = 100
def fn1():
x +=1
print(f"函數內的{x}")
fn1()
print(f"變更后的{x}")
運行結果:
為什么會運行報錯:X在使用前需要先分配變量值,明明我們在全局已經定義了一個X=100
原因:在python動態語言內,== 賦值即定義== ,在inner內部
- x += 1其實是一個x = x+1的賦值語句,那這個x就會函數運行在初始化進行加載,變成局部的一個變量
- 而=運算時,從左往右執行,在x=的時候已經默許了x是local variable,因此外部作用域的x=100是被屏蔽的。所以x+1中的x相當于一個沒有賦值的變量,從而報錯。
那么怎么解決這個問題?解決的辦法一:使用global關建字將x定義為全局變量,這時在函數局部就會將x指向全局的變量x
讓我們來看看具體的應用,下面的代碼運行結果如何:
x = 100
def fn1():
x = 10
global x
x +=1
print(f"函數內的{x}")
fn1()
print(f"變更后的{x}")
運行結果:
為什么還是報錯,我們不是已經使用了global嗎?那是因為我們前面聲明前加了一句:x = 10
x = 10 時會將其置為局部變量,但程序執行到global x時,發現x已經在局部定義過了,所以報錯,所以我們要先聲明再調用
所以我們將程序調整為:
那么問題又來了,下面的例子,global x在inner函數內可以調用嗎?
x = 100
def outer():
global x
x +=1
print(f"ouer的x調用結果{x}")
def inner():
x +=1
print(f"inner的x調用結果{x}")
return inner
a = outer()
a()
運行結果:
為什么報錯,不是已經定義了global全局變量,同時也是局部作用域內先定義了嗎?
原因:Global 定義只在全局和定義的當前作用域內起作用,所以上面的例子,global x只在全局作用域和嵌套作用域內可用,如果inner內部想調用,需要做以下調整
特別說明:
global關鍵字是一種破壞函數封裝的方式,變量未經過傳參即可在函數內部作用域內使用。所以在日常使用中,**不要使用,那我們要實現這種調用,可以用什么方式呢?python給我提供了一個關鍵字:Nolocal,后續我的筆記中會詳細提到
原文鏈接:https://blog.csdn.net/totorobig/article/details/126687921
相關推薦
- 2023-04-07 C#快速實現IList非泛型類接口的自定義類作為數據源_C#教程
- 2022-04-29 C#實現實體類和XML的相互轉換_C#教程
- 2022-09-30 Flutter?日歷組件簡單實現_Android
- 2022-12-10 Qt顯示QImage圖像在label上,并保持自適應大小問題_C 語言
- 2022-03-31 python常用內置模塊你了解嗎_python
- 2022-12-10 C++實現線程同步的四種方式總結_C 語言
- 2022-05-12 Android 截屏實現、屏幕截圖、MediaProjection、ImageReader
- 2022-08-22 Git遠程刪除某個歷史提交記錄方法詳解_相關技巧
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支