Python inner functions
在python中,我可以写:
1 2 3 4 5 6 7 8 9 10 11 | def func(): x = 1 print x x+=1 def _func(): print x return _func test = func() test() |
当我运行它时,输出是:
一
二
因为func可以访问func中定义的"x"变量。正确的。。。
但如果我这样做:
1 2 3 4 5 6 7 8 9 10 11 | def func(): x = 1 print x def _func(): x+=1 print x return _func test = func() test() |
然后我收到一条错误消息:unboundlocalerror:在赋值之前引用了局部变量"x"
在这种情况下,似乎func看不到"x"变量
问题是:为什么第一个示例中的print x"看到"了"x"变量,而数学运算符x+=1抛出了一个异常?
我不明白为什么…
检查这个答案:https://stackoverflow.com/a/293097/1741450
Variables in scopes other than the local function's variables can be accessed, but can't be rebound to new parameters without further syntax. Instead, assignment will create a new local variable instead of affecting the variable in the parent scope. For example:
考虑到python是一种"解释"语言,我们自然会假设,如果一个变量已经在外部范围中定义,那么在内部范围中仍然可以访问该变量。实际上,在第一个例子中,当内部的
但是,关于python不明显的一点是,这并不是确定变量范围的确切方法。python在编译时根据变量是否在某个范围内被分配,分析哪些变量应该被认为是"局部"的。在这种情况下,赋值包括增广的赋值运算符。因此,在第二个示例中,当Python将内部的
另一种看问题的方法可能是写如下内容:
1 2 3 | def _func(): print x x = 2 |
这里再次说明,由于
您可以使用
1 2 3 4 5 6 7 8 9 | >>> dis.dis(_func) 2 0 LOAD_FAST 0 (x) 3 PRINT_ITEM 4 PRINT_NEWLINE 3 5 LOAD_CONST 1 (2) 8 STORE_FAST 0 (x) 11 LOAD_CONST 0 (None) 14 RETURN_VALUE |
您可以检查函数本身(特别是它的基础代码对象),该代码中使用了一个局部变量,并且与之关联的变量名是
1 2 3 4 | >>> _func.__code__.co_nlocals 1 >>> _func.__code__.co_varnames ('x',) |
这就是
为了理解Python中的变量范围,这些都不是必需的,但是了解引擎盖下发生了什么仍然是有帮助的。
正如在其他一些答案中已经提到的,python 3引入了
不能重新绑定在python 2中关闭的变量(可以在python 3中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Pointer(object): def __init__(self, val): self.val = val def func(): px = Pointer(1) print px.val px.val += 1 def _func(): print px.val return _func test = func() test() |
基本上,我把需要改变的任何值放到一个对象上——有时我使用一个元素列表——然后重新编写代码,这样所发生的一切就是方法调用。以上实际上相当于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Pointer(object): def __init__(self, val): self.val = val def func(): px = Pointer(1) print px.val px.__setattr__('val', px.val + 1) def _func(): print px.val return _func test = func() test() |