python 關於 for循環 命名空間和變數作用域的一個疑問?

我是在一次幫朋友寫腳本的過程中產生的這個疑問:
舉例:

def calcAverage(dictContent):
dictAverage = dict()
for (key,values) in dictContent.items():
dictAverage.setdefault(key,list())
intSumValue = 0
#n = 0
intMax = max(values)
intMin = min(values)
for n,value in enumerate(values):
intSumValue += float(value)
else:
average = intSumValue/(n+1)
print average
dictAverage[key].append(intSumValue)
dictAverage[key].append(n+1)
dictAverage[key].append(intMax)
dictAverage[key].append(intMin)
dictAverage[key].append(average)
return dictAverage

我在for循環外面想使用n這個變數。。。竟然成功了。
我記得在C語言裡面是不可以的。

pyhton關於變數的作用域的規定 是如何解釋的?


Python 的作用域遵循一個叫做LEGB的法則。

當 Python 遇到一個變數的話他會按照這樣的順序進行搜索:

本地作用域(Local)→當前作用域被嵌入的本地作用域(Enclosing locals)→全局/模塊作用域(Global)→內置作用域(Built-in)

使用 class, def, lambda 會引入一個本地作用域(Local),而且本地作用域是可以嵌套的。內層的變數會屏蔽外層,內層找不到的變數會去外層找

全局作用域(Global)就是模塊內的作用域,他的作用範圍是單一文件內。

內置函數的作用域就是int(), list()之類的內置函數。

舉個栗子:

a1 = 1 # Global

class Foo:
a2 = 1 # Local

def func():
a3 = 1 # Local
def _func():
a5 = 1 # Local
for i in range(3):
a4 = 1 # Local 和 a3 在同一個作用域,因為 for 不會引入新的作用域

上述代碼中作用域的範圍是 a1 &> a2 &> a3 == a4 &> a5

PS:你也可以使用 global 語句 和 nonlocal 語句來改變他們的作用域


@馮昱堯 已經解釋了python作用域的基本搜索規則。實際碰到的python作用域問題也遠比這個規則複雜得多。

但並沒有解釋樓主提出的問題,「for循環內的變數為何可以在for循環結束後繼續被訪問。」

在 7. Compound statements 中是這麼說的:

The for-loop makes assignments to the variable(s) in the target list.
This overwrites all previous assignments to those variablees including those made in the suite of the for-loop.

The target list is not deleted when the loop is finished.
But if the sequence is empty, they will not have been assigned to at all the loop.

也就是說for循環中的target list(for x in range(10) x 就是target list)在循環結束中並未被刪除,可以被後續程序直接使用。但除一種情況外:循環序列為空時,target list根本不會被賦值。

這個根源還在於,Python中的for循環並沒有引入作用域(scope)的概念,但函數定義有引入作用域
什麼意思呢?
如果你希望for循環變數不被其他程序誤用/覆蓋等,可以把for循環單獨放在一個函數內。

舉個例子:

def handleForLoop(seq):
for x in seq:
# Do something
return

這樣變數x是安全的。

這裡有一篇文章很詳細的分析了這個問題:Python名空間和作用域窺探。


剛遇到這問題,查了下:

PYTHON的作用域由def、class、lambda等語句產生,if、try、for等語句並不會產生新的作用域。變數名引用分為三個作用域進行查找:首先是本地,然後是函數內(如果有的話),之後是全局,最後是內置。


推薦閱讀:

Python到底有多慢?
如何从拉勾网往里面来看互联网企业里面的数据挖掘现状如何?
python要學到一個什麼樣的程度能找到個一般的工作?
實際應用中python編寫的程序大部分都是無界面的嗎?
Python學到什麼樣子可以去找工作?

TAG:Python | Python入門 | 命名空間 |