2010-11-27 35 views
9

我想了解,python中的变量绑定工作原理。让我们看看这个:python:如何绑定工作

def foo(x): 
    def bar(): 
     print y 
    return bar 

y = 5 
bar = foo(2) 
bar() 

这打印出5对我来说似乎是合理的。

def foo(x): 
    def bar(): 
     print x 
    return bar 
x = 5 
bar = foo(2) 
bar() 

这打印2,这很奇怪。在第一个例子中,python在执行期间查找变量,在第二个时候创建​​方法。为什么这样?

要清楚:这是非常酷,并按我的愿望工作。但是,我对内部条形函数如何获取其上下文感到困惑。我想了解,发生了什么。

编辑

我知道,局部变量有更大的优先权。我很好奇,python在执行过程中如何知道我之前调用的函数的参数。 bar创建于foox不存在。函数创建时,它是否已将此x绑定到参数值?

回答

0

没什么奇怪的,这是因为函数参数的“x”比全局变量“x”的优先级高。

首先,全局变量是一个巨大的罪恶。

Python有运营商的“全球”:

>>> def foo(x): 
...  def bar(): 
...   global x 
...   print x 
...  return bar 
... 
>>> x = 5 
>>> bar = foo(2) 
>>> bar() 
5 
0

它的范围母校,第二个示例使用本地范围变量X,即先全局声明

7

,你是暗指的问题是词汇VS的蟒蛇变量动态作用域之一。为了明确,python定义了以下四个范围。

  1. 最里面的范围,这是第一次搜索,包含本地名
  2. 中所有的封闭功能,其被搜索开始与最近的封闭范围的范围,包含非本地的,也有非全局名称
  3. 下一个到最后一个范围包含当前模块的全局名称
  4. 最外层的范围(最后搜索)是一个包含内置名字

在第一个例子中的命名空间,W这里“y”定义在功能栏的外部,python搜索最内层的范围并向上移动链,直到在模块中找到全局变量“y”

在第二个示例中,“x”在由函数foo(x)定义,x属于封闭函数的范围,当它被打印在bar内部时。用纯粹的术语来说,封闭已经被定义。

有关在Python作用域进一步的研究,我发现下面article一个伟大的阅读

1

在这两个例子中,查找发生在运行时。唯一的区别是,有一个本地定义的变量x,而没有本地定义的变量y

当执行...

def foo(x): 
    def bar(): 
     print y 

    return bar 

y = 5 
bar = foo(2) 
bar() 

...的print语句查找名为y变量,只有发现它在全球范围内,所以它使用的那一个,并打印“5”。

在...

def foo(x): 
    def bar(): 
     print x 

    return bar 

x = 5 
bar = foo(2) 
bar() 

...当查找发生时,限定的范围的变量x - 其被固定为 “5”,当foo函数被调用。

关键是参数在传递给函数时被评估,因此外部函数foo会计算调用时传入的参数。这有效地在foo函数的上下文中创建了一个名为x的变量,因此无论何时执行bar,它都会看到该变量,而不是全局定义的变量。

这可以偶尔会造成混淆,如下面的代码:

lst = [] 
for i in range(5): 
    x = i 
    lst.append(lambda: x) 

for func in lst: 
    print func() # prints 4 4 4 4 4 

你需要做的:

lst = [] 
for i in range(5): 
    def _func(x): 
     return lambda: x 

    lst.append(_func(i)) 

for func in lst: 
    print func() # prints 0 1 2 3 4