有了函式之後,我們必須要面對乙個作用域的問題。
比如:你現在訪問乙個變數,那麼 python 解析器是怎麼查詢到這個變數,並讀取到這個變數的值的呢? 依靠的就是作用域規則!
作用域(scope
)
作用域就是 python 程式的一塊文字區域,在這個區域內,可以直接訪問(directly accessible)命名空間。
直接訪問的意思就是:當你訪問乙個絕對的命名的時候,直接在命名空間中查詢
儘管作用域的定義是靜態的,但是作用域的使用(查詢變數)卻是動態的。
在**執行的任何時間,至少有 3 個巢狀的作用域,這些作用域的命名空間可以直接訪問。
內部作用域(區域性作用域)。包含了所有的區域性命名,在訪問變數的時候,首先在內部作用域中查詢。
然後是巢狀函式的外層作用域。在這裡搜尋非區域性,但也是非全域性的命名。(在 python 中允許在函式中定義函式的)
然後是包含當前模組的全域性作用域。
最後搜尋的是最外層的建立內建命名的作用域。
l:區域性的(local)3.2.1.訪問區域性作用域e:封閉的(enclosing)
g:全域性的(global)
b:內建的(built-in)
一、區域性命名空間
函式內部的命名空間,在呼叫函式的時候生成,呼叫結束時消失。當區域性命名空間有效時,它是第乙個用於檢查某個名字存在性的命名空間。如果在區域性命名空間內找到該名稱,則返回與名字相關聯的物件,反之提示出錯。
def foo():
a = 20
print(a)
foo()
說明:
函式內部訪問變數a
, 先在foo
函式內部查詢。因為a
確實是在函式內部宣告的變數,然後就找到了a
3.2.2.訪問外部作用域
a = 100
def foo():
print(a)
foo()
說明:
在foo
函式內部,我們直接去訪問乙個變數a
,那麼就會沿著作用域從內向外開始查詢a
先查詢foo
的區域性作用域,發現沒有a
。然後繼續去foo
函式的外部作用域,這個例子中就直接到了當前模組的全域性作用域,所以找到了 a, 所以就輸出了全域性作用域中a
的值!
3.2.3.訪問外部函式的作用域
def outer():
a = 20
def inner():
print(a)
inner()
outer()
說明:
我們在乙個函式的內部宣告了一函式,這種函式巢狀在 python 中是允許的。
內部函式inner
執行的時候,訪問變數a
,現在inner
內部找變數a
, 沒有找到,然後去他外部的函式中找變數a
, 找到後, 就直接輸出了他的值
3.2.4 python 針對修改變數值的特殊情況
3.2.4.1.只能修改區域性變數
在 python 的函式中, 修改乙個變數的值的時候,永遠操作的是區域性變數
為什麼會這樣呢?
這其實是由 python 定義變數的方式所決定的.
python 不需要顯示的去定義變數,直接賦值的時候如果變數不存在直接就定義了.
如果在函式內部可以直接修改外部作用域變數的值,則就無法定義乙個同名變數了.
所以, python 才規定不能在函式內部直接修改外部作用域變數的值.
a = 10
def foo():
a = 20 # 這裡其實是新建立了乙個區域性變數 a .並不是修改的全域性作用域的變數 a
print(a) # 根據作用域的查詢規則,這裡訪問的是區域性變數 a
foo()
print(a) # 根據作用域查詢規則,這裡訪問的是全域性作用域的 a
3.2.4.2.變數必須先賦值才能使用
看下面的**:
說明:
a = a + 2
這行**有問題. 為什麼?
首先要搞清楚a + 2
中的a
是區域性變數還是全域性變數?
是區域性變數a
!
在直譯器執行這個函式的時候, 已經檢測到函式內部有建立區域性變數a
, 所以這個時候你訪問到的一定是區域性變數a
.
a + 2
中的區域性變數a
還沒有 被賦值,所以和 2 相加丟擲了異常.unboundlocalerror
(區域性變數錯誤)
說明:原因和前面的一樣的.
解析器已經檢測到你後面會宣告區域性變數a
, 所以print(a)
中的a
仍然是區域性變數.但是還沒有賦值,所以就拋異常了
總結:
在函式內部如果你定義了區域性變數,那麼你在任何地方都沒有辦法訪問到函式外部作用域的同名變數.
3.2.4.3 函式內修改全域性變數
通過前面的學習, 正常情況下我們知道了在函式內部沒有辦法修改全域性變數的值!
但是這只是正常情況下!
如果我們有在函式內部修改全域性變數值的需求怎麼辦?
也是可以的, 但是我們需要做些小動作: 使用關鍵字global
a = 10
def foo():
global a # 告訴 python 解析器, a 以後就是全域性變數了
a = 20
foo()
print(a) # 20
說明:global
後面跟上全域性變數的名, 那麼在後面的**中就可以使用全域性變數了.
如果有多個全域性變數需要修改,global
可以同時定義多個全域性變數.global a, b, c
3.2.4.4內部函式修改外部函式的區域性變數
當用到函式巢狀的時候, 內部函式正常情況下也是無法修改外部函式的區域性變數, 只能訪問讀取.
如果想修改怎麼辦?
使用關鍵字:nonlocal
a = 10
def outer():
a = 20
def inner():
nonlocal a # 把 a 繫結到外部函式的區域性變數 a 上
a = 30
inner()
print("outer 的區域性變數a:" + str(a)) # 30 被內部函式 inner 修改了
outer()
#print("全域性變數a:%d"%a)
#print("全域性變數a:",a)
print("全域性變數a:" + str(a))
cin中函式的作用(第5章)
cin是istream類的物件,它是從標準輸入裝置 鍵盤 獲取資料,程式中的變數通過流提取符 從流中提取資料。流提取符 從流中提取資料時跳過輸入流中的空格 tab鍵 換行符等空白字元。注意 只有在輸入完資料再按回車鍵後,該行資料才被送入鍵盤快取區,形成輸入流,提取運算子 才能從中提取資料。需要注意保...
函式的作用域
一,每乙個變數都是有作用域的。1,首先講一下 塊與作用域 for,if等語句還有 function,他們都有乙個特點,就是後面有一對 比如 for var i 0 i items.length i 之間有 if some express 之間有 function param1 之間有 所有 包起來的...
函式的作用域
在php中,函式的作用域來控制函式及函式中的變數在 是可見並且可用的。不同的程式語言有不同的變數作用域規則,php中的函式及函式中的變數作用域規則如下 函式的作用域是指在函式內部宣告的變數作用域是從宣告的那條語句開始到函式的末尾 全域性作用域是指在函式外部宣告的變數作用域是從那條語句開始到宣告所在的...