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