2012-08-05 16 views
11

的代碼是從pyquery的導向爲什麼這個未綁定的變量可以在Python(pyquery)中工作?

from pyquery import PyQuery 
d = PyQuery('<p class="hello">Hi</p><p>Bye</p>') 
d('p').filter(lambda i: PyQuery(this).text() == 'Hi') 

我的問題是在第三線this是未結合的可變的並且從未在當前環境中定義,但上述代碼仍然有效。

它是如何工作的?爲什麼它不會投訴NameError: name 'this' is not defined

看來有什麼事發生在https://bitbucket.org/olauzanne/pyquery/src/c148e4445f49/pyquery/pyquery.py#cl-478,有人可以解釋嗎?在其定義的功能模塊的全局命名空間 -

+1

謝謝,我從來沒有聽說過PyQuery。絕對會嘗試和使用它。 – Blender 2012-08-05 07:56:09

+0

同樣在這裏。從來不知道PyQuery之前,聽起來有趣.. – SuperSaiyan 2012-08-05 08:05:07

回答

4

這是通過Python的func_globals魔術,這是

到存放函數的全局變量的參考字典來完成。

如果你潛入PyQuery代碼:

def func_globals(f): 
    return f.__globals__ if PY3k else f.func_globals 

def filter(self, selector): 
    if not hasattr(selector, '__call__'): 
     return self._filter_only(selector, self) 
    else: 
     elements = [] 
     try: 
      for i, this in enumerate(self): 

       # The magic happens here 
       func_globals(selector)['this'] = this 

       if callback(selector, i): 
        elements.append(this) 

     finally: 
      f_globals = func_globals(selector) 
      if 'this' in f_globals: 
       del f_globals['this'] 
     return self.__class__(elements, **dict(parent=self)) 
+0

謝謝,BasicWolf。但是,對於我來說,這在枚舉(self)中有什麼意義,爲什麼會是一個設置'func_globals(selector)['this']'的值的循環? – 2012-08-05 15:26:58

+0

好吧,枚舉從一個iterable中創建一個[(index,element)]序列(PyQuery類可以作爲'list'的子類迭代)。因此,'i'是元素的索引,'this'是指存儲在PyQuery對象中的元素。瞭解PyQuery如何深入研究的最好方法是深入研究其代碼。 – 2012-08-05 16:40:12

-2

這不會引發NameError因爲變量可能在實際的函數被調用時存在。

>>> f = lambda i: some_non_named_var 
>>> f(1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <lambda> 
NameError: global name 'some_non_named_var' is not defined 

只有在您調用已隱藏的函數後,上述內容纔會出錯。在您顯示的示例代碼中,在調用lambda selector函數之前,他們在func_globals中手動設置一個名爲this的變量。

+0

爲什麼這是downvoted?它可能不像其他一些答案那樣完整,但它仍然可以確切地說明發生了什麼。 – 2012-09-14 01:44:53

1

其他人已經正確指出this是如何在你正在談論的lambda中定義的。

更詳細地說明了一下,試試下面的代碼:

>>> def f(): 
...  print f_global 
... 
>>> f() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in f 
NameError: global name 'f_global' is not defined 
>>> f.__globals__['f_global'] = "whoa!!" #Modify f()'s globals. 
>>> f() 
whoa!! 

這正是發生在那裏。 On line 496, you would see the following code

for i, this in enumerate(self):    #this is the current object/node. 
    func_globals(selector)['this'] = this #func_globals returns selector.__globals__ 
相關問題