Reputation: 6764
It looks strange. A variable with a name classes is printed but is undefined when trying to execute filter(...)
contruction.
Here is a code:
def start(self, tag, attrib):
classes = attrib[self._CLASS_ATTR] if self._CLASS_ATTR in attrib else None
if tag == self._TAG_P:
p = self._doc.add_paragraph('')
self._cur_p = p
if classes is not None:
alignments = [self._left_align, self._center_align, self._right_align]
import pdb; pdb.set_trace()
alignments = filter(lambda x: partial(x.is_in, classes), alignments)
if len(alignments) > 0:
p.alignment = alignments[0].get()
assert len(alignments) < 2
Pdb stops on it's break. When I try to execute filter()
:
(Pdb) print filter(lambda x: partial(x.is_in, classes), alignments)
*** NameError: global name 'classes' is not defined
But:
(Pdb) print classes
center title
(Pdb) classes
u'center title'
Why the filter(...)
instruction could not be executed normally?
Let's reproduce it in short code:
from functools import partial
def f():
classes = 'my_classes'
def my_bool(obj, _):
return True
if classes is not None:
import pdb; pdb.set_trace() # point a
alignments = filter(lambda x: my_bool(x, classes), ['1', '2', '3'])
import pdb; pdb.set_trace() # point b
pass
f()
...
(Pdb) filter(lambda x: my_bool(x, classes), ['1', '2', '3'])
*** NameError: global name 'my_bool' is not defined
However, the command c
(continue) of pdb in point a
does not generate an exception.
Upvotes: 2
Views: 1030
Reputation: 70147
pdb
is an eval
loop. An eval loop essentially takes what you write to the prompt line by line and eval(...)
s it. This means it doesn't bind closure-scoped variables in defined functions (lambdas). eval
(which is a function) has its own scope and doesn't participate in the closure you are evaluating in.
You can see the equivalent problem from this example code:
def f():
x = 1
return eval('lambda: x')
>>> f()()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
NameError: name 'x' is not defined
An (unfortunate) workaround is to define any lambdas up-front and use them in your pdb expression.
Upvotes: 2