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他の人は、あなたが話しているラムダ内でどのように定義されているかを正しく指摘しています。

もう少し詳しく説明するには、次のコードを試してください。

>>> 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

上記は、隠した関数を呼び出すまでエラーになりません。あなたが示したコード例では、ラムダ関数を呼び出す前に、で呼び出さthisれた変数を手動で設定しています。func_globalsselector

于 2012-08-05T08:18:00.403 に答える