11

代码来自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在第 3 行是一个未绑定的变量,并且从未在当前环境中定义,但上面的代码仍然有效。

它如何工作?为什么它不抱怨NameError: name 'this' is not defined

似乎在https://bitbucket.org/olauzanne/pyquery/src/c148e4445f49/pyquery/pyquery.py#cl-478发生了一些事情,有人可以解释一下吗?

4

3 回答 3

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))
于 2012-08-05T08:15:32.700 回答
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!!

这正是那里正在发生的事情。在第 496 行,您将看到以下代码

for i, this in enumerate(self):             #this is the current object/node.
     func_globals(selector)['this'] = this  #func_globals returns selector.__globals__
于 2012-08-05T08:21:25.063 回答
-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函数之前手动设置了一个调用this的变量。func_globalsselector

于 2012-08-05T08:18:00.403 回答