2010-11-27 67 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