def some_func(a):
def access_a():
print(a)
access_a()
输出a
的值。但是,如果我想在嵌套函数中更改a
,请执行以下操作:
def some_func(a):
def change_a():
a += 1
print(a)
change_a()
它引发UnboundLocalError
例外。
我知道a
是一个非本地变量,但为什么我可以在不声明nonlocal a
的情况下访问它?
答案 0 :(得分:2)
Python范围规则101:
在函数体中绑定的名称被视为local
,除非明确声明global
(Python 2.x和3.x)或nonlocal
(仅限Python 3.x) )。无论赋值发生在函数体内,这都适用。在绑定之前尝试读取局部变量当然是一个错误。
如果读取了一个名称但未在函数体中绑定,则将在封闭的范围中查找(如果有任何全局范围,则在外部函数中查找)。注意:函数参数是事实上的本地名称,因此它们永远不会被封闭的范围内查找。
请注意,a += 1
主要是a = a + 1
的快捷方式,因此在您的示例中a
是本地的(绑定在函数体内,而不是明确声明为全局或非本地),但是您尝试在它被束缚之前阅读它(a = a+1
的rhs。)
在Python 3中,您可以使用nonlocal
语句解决此问题:
>>> def outer(a):
... def change():
... nonlocal a
... a += 1
... print("before : {}".format(a))
... change()
... print ("after : {}".format(a))
...
>>> outer(42)
before : 42
after : 43
Python 2没有nonlocal
所以规范的hack是将变量包装在一个可变容器中(通常是list
,但任何可变对象都可以):
>>> def outer(a):
... _a = [a]
... def change():
... _a[0] += 1
... print("before : {}".format(_a[0]))
... change()
... print ("after : {}".format(_a[0]))
...
>>> outer(42)
before : 42
after : 43
至少可以说这是非常难看的。
现在虽然闭包非常方便,但它们大部分都是对象的功能对应物:一种在保留这种状态封装的同时在一组函数之间共享状态的方法,所以如果你发现需要一个{{1}变量也许一个合适的类可能是一个更清晰的解决方案(虽然可能不是你的例子不返回内部函数但只在内部使用它)。
答案 1 :(得分:1)
我有两个解决方案:
#first one:
# try with list, compound data types dict/list
def some_func(a):
def change_a():
a[0] += 1
print(a[0])
change_a()
some_func([1])
>>> 2
#second one
#reference pointer
from ctypes import *
def some_func_ctypes(a):
def change_a():
a[0] += 1
print a.contents, a[0]
change_a()
i = c_int(1)
pi = pointer(i)
some_func_ctypes(pi)
>>> c_int(2) 2
答案 2 :(得分:0)
使用a
运算符时,会为http = require('http');
server = http.createServer();
Primus = require('primus');
primus = new Primus(server, {
transformer: 'websockets',
pathname: 'ws'
});
primus.on('connection', function connection(spark) {
console.log("client has connected");
spark.write("Herro Client, I am Server");
spark.on('data', function(data) {
console.log('PRINTED FROM SERVER:', data);
spark.write('receive '+data)
});
spark.on('error', function(data) {
console.log('PRINTED FROM SERVER:', data);
spark.write('receive '+data)
});
});
server.listen(5431);
console.log("Server has started listening");
分配一个新值。这使得翻译者眼中的本地化。