網站首頁 編程語言 正文
1.命名空間
先看看官方文檔的一段話:
命名空間(Namespace)是從名稱到對象的映射,大部分的命名空間都是通過 Python 字典來實現的。
命名空間提供了在項目中避免名字沖突的一種方法。各個命名空間是獨立的,沒有任何關系的,所以一個命名空間中不能有重名,但不同的命名空間是可以重名而沒有任何影響。
我們舉一個計算機系統中的例子,一個文件夾(目錄)中可以包含多個文件夾,每個文件夾中不能有相同的文件名,但不同文件夾中的文件可以重名。
一般有三種命名空間:
- 內置名稱(built-in names), Python 語言內置的名稱,比如函數名 abs、char 和異常名稱 BaseException、Exception 等等。
- 全局名稱(global names),模塊中定義的名稱,記錄了模塊的變量,包括函數、類、其它導入的模塊、模塊級的變量和常量。
- 局部名稱(local names),函數中定義的名稱,記錄了函數的變量,包括函數的參數和局部定義的變量。(類中定義的也是)
命名空間查找順序:
假設我們要使用變量 lizexiong,則 Python 的查找順序為:局部的命名空間去 -> 全局命名空間 -> 內置命名空間。
如果找不到變量 lizexiong,它將放棄查找并引發一個 NameError 異常:
NameError: name 'lizexiong' is not defined。
命名空間的生命周期:
命名空間的生命周期取決于對象的作用域,如果對象執行完成,則該命名空間的生命周期就結束。
因此,我們無法從外部命名空間訪問內部命名空間的對象。
# var1 是全局名稱
var1 = 5
def some_func():
# var2 是局部名稱
var2 = 6
def some_inner_func():
# var3 是內嵌的局部名稱
var3 = 7
如下圖所示,相同的對象名稱可以存在于多個命名空間中。
2.作用域
作用域就是一個 Python 程序可以直接訪問命名空間的正文區域。
在一個 python 程序中,直接訪問一個變量,會從內到外依次訪問所有的作用域直到找到,否則會報未定義的錯誤。
Python 中,程序的變量并不是在哪個位置都可以訪問的,訪問權限決定于這個變量是在哪里賦值的。
變量的作用域決定了在哪一部分程序可以訪問哪個特定的變量名稱。Python 的作用域一共有4種,分別是:
有四種作用域:
- L(Local):最內層,包含局部變量,比如一個函數/方法內部。
- E(Enclosing):包含了非局部(non-local)也非全局(non-global)的變量。比如兩個嵌套函數,一個函數(或類) A 里面又包含了一個函數 B ,那么對于 B 中的名稱來說 A 中的作用域就為 nonlocal。
- G(Global):當前腳本的最外層,比如當前模塊的全局變量。
- B(Built-in): 包含了內建的變量/關鍵字等,最后被搜索。
規則順序: L –> E –> G –> B。
在局部找不到,便會去局部外的局部找(例如閉包),再找不到就會去全局找,再者去內置中找。
g_count = 0 # 全局作用域
def outer():
o_count = 1 # 閉包函數外的函數中
def inner():
i_count = 2 # 局部作用域
內置作用域是通過一個名為 builtin 的標準模塊來實現的,但是這個變量名自身并沒有放入內置作用域內,所以必須導入這個文件才能夠使用它。在Python3.0中,可以使用以下的代碼來查看到底預定義了哪些變量:
>>> import builtins
>>> dir(builtins)
Python 中只有模塊(module),類(class)以及函數(def、lambda)才會引入新的作用域,其它的代碼塊(如 if/elif/else/、try/except、for/while等)是不會引入新的作用域的,也就是說這些語句內定義的變量,外部也可以訪問,如下代碼:
>>> if True:
... msg = 'I am from Lizexiong'
...
>>> msg
'I am from Lizexiong'
>>>
實例中 msg 變量定義在 if 語句塊中,但外部還是可以訪問的。
如果將 msg 定義在函數中,則它就是局部變量,外部不能訪問:
>>> def test():
... msg_inner = 'I am from Lizexiong'
...
>>> msg_inner
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'msg_inner' is not defined
>>>
從報錯的信息上看,說明了 msg_inner 未定義,無法使用,因為它是局部變量,只有在函數內可以使用。
全局變量和局部變量
定義在函數內部的變量擁有一個局部作用域,定義在函數外的擁有全局作用域。
局部變量只能在其被聲明的函數內部訪問,而全局變量可以在整個程序范圍內訪問。調用函數時,所有在函數內聲明的變量名稱都將被加入到作用域中。
如下實例:
total = 0 # 這是一個全局變量
# 可寫函數說明
def sum( arg1, arg2 ):
#返回2個參數的和."
total = arg1 + arg2 # total在這里是局部變量.
print ("函數內是局部變量 : ", total)
return total
#調用sum函數
sum( 10, 20 )
print ("函數外是全局變量 : ", total)
以上實例輸出結果:
函數內是局部變量 : ?30
函數外是全局變量 : ?0
global 和 nonlocal關鍵字
當內部作用域想修改外部作用域的變量時,就要用到 global 和 nonlocal 關鍵字了。
以下實例修改全局變量 num:
num = 1
def fun1():
global num # 需要使用 global 關鍵字聲明
print(num)
num = 123
print(num)
fun1()
print(num)
以上實例輸出結果:
1
123
123
如果要修改嵌套作用域(enclosing 作用域,外層非全局作用域)中的變量則需要 nonlocal 關鍵字了,如下實例:
def outer():
num = 10
def inner():
nonlocal num # nonlocal關鍵字聲明
num = 100
print(num)
inner()
print(num)
outer()
以上實例輸出結果:
100
100
另外有一種特殊情況,假設下面這段代碼被運行:
'''
學習中遇到問題沒人解答?小編創建了一個Python學習交流群:711312441
尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書!
'''
a = 10
def test():
a = a + 1
print(a)
test()
以上程序執行,報錯信息如下:
Traceback (most recent call last):
File "test.py", line 7, in <module>
test()
File "test.py", line 5, in test
a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment
錯誤信息為局部作用域引用錯誤,因為 test 函數中的 a 使用的是局部,未定義,無法修改。
修改 a 為全局變量:
a = 10
def test():
global a
a = a + 1
print(a)
test()
執行輸出結果為:
11
也可以通過函數參數傳遞:
a = 10
def test(a):
a = a + 1
print(a)
test(a)
執行輸出結果為:
11
原文鏈接:https://blog.csdn.net/qdPython/article/details/127703400
相關推薦
- 2022-03-24 Android繪制平移動畫的示例代碼_Android
- 2022-08-12 Go本地測試小技巧解耦任務拆解_Golang
- 2022-05-15 Docker基本概念和底層原理解析_docker
- 2022-08-05 Entity?Framework主從表數據加載方式_C#教程
- 2022-12-27 NSURLSession跨域重定向透傳HTTP?Header問題解決_IOS
- 2022-09-30 Python中4種實現數值的交換方式_python
- 2022-03-26 c++?KMP字符串匹配算法_C 語言
- 2022-11-23 一文教會你用正則表達式校驗日期時間格式_正則表達式
- 最近更新
-
- 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同步修改后的遠程分支