Python範圍適合3類 - local
,nonlocal
和global
。默認情況下,函數只能在本地作用域中更改引用(引用是使用賦值運算符創建的)。
你可以自由地發生變異你有一個參考的對象這就是爲什麼第二個例子作品(i
是列表[1]
的引用,那麼你改變/突變它的第一項)。總之,你是突變i
引用的對象,你不是試圖改變引用。需要注意的是,你可以給一個函數訪問通過global
關鍵字來改變在全球範圍內的參考:
i = 1
def func():
global i # If you comment this out, i doesn't get changed in the global scope
i = 2
func()
print(i) # 2 -- 1 if the global statement is commented out.
注意python3.x添加nonlocal
關鍵字。它與global
的作用相同,但與非本地範圍相同。例如
def foo():
i = 1 # nonlocal to bar
def bar():
nonlocal i
print(i)
i += 1
return bar
bar1 = foo()
bar1() # 1
bar1() # 2
bar1() # 3
bar2 = foo()
bar2() # 1
bar2() # 2
bar1() # 4 bar2 doesn't influence bar1 at all.
增強運營商
這是更先進一些,但提供給希望能幫助回答有關像+=
運營商的問題。考慮這樣的情況:
x = []
def func():
x += [1]
你可能認爲這個工作 - 畢竟,x += [1]
的列表x
真的只是x.extend([1])
,吧?。不幸的是,這並不完全。我們可以使用dis.dis
反彙編func
以查看更多信息。
>>> dis.dis(func)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (1)
6 BUILD_LIST 1
9 INPLACE_ADD
10 STORE_FAST 0 (x) ### IMPORTANT!
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
注意字節碼指令STORE_FAST
?基本上說,將INPLACE_ADD
的結果存儲在本地字典中的名稱x
中。換句話說,你寫的:
x += [1]
但是Python執行:
x = x.__iadd__([1])
爲什麼? __iadd__
應該在適當的位置操作,爲什麼它需要重新命名爲__iadd__
的返回值?重新綁定的部分是問題 - 即這段代碼將工作:
x = []
def func():
x.__iadd__([1])
答案是因爲Python有不可變對象和__iadd__
需要與他們合作過。因此,__iadd__
可以返回「self
」以外的對象。這最終是非常有用的。考慮i = 1; i += 1
。此調用僅適用於int.__iadd__
被允許返回一個新的整數。
在更深入的討論其實這是我的所有時間在計算器上最upvoted答案,可以發現here
你能不能也包括這樣的:'我= []; def x():i + = [2]' - 爲什麼這不起作用?列表上的'+ ='不會重新分配任何東西...... – georg 2014-10-16 16:09:24
@georg - 當然可以。該任務只是有點隱藏。如果你使用'dis'反彙編這個函數,你會看到'STORE_FAST ...(i)'指令。 'i + = something'調用'i .__ iadd __(something)',並將返回值存儲在本地範圍內的名稱'i'中。如果沒有,'+ ='不適用於不可變對象(即'int')。注意['cls .__ iadd__'應該(但不一定)爲可變對象返回'self',爲不可變對象返回一個新實例](https://docs.python.org/2/reference/datamodel.html #object .__ iadd__)。 – mgilson 2014-10-16 16:17:27
謝謝))我的意思是,你不認爲這是值得添加到你的答案? – georg 2014-10-16 16:24:33