0

I have some data (in a pandas.DataFrame), which I want to apply some filters to. I seemed proper to define a dictionary of filter functions, which for one case of filtering were supposed to be just constant comparisons, but I need flexibility of other boolean tests. So I tried defining a filter like this.

In pure Python 3.3.5, this works.

>>> center = {"A": 1, "B": 0}
>>> filters = {key: (lambda x: x==value)
...   for key, value in center.items()}
>>> filters["A"](1)
True

In IPython 2.3.0, using that Python 3, it works as well.

In [1]: center = {"A": 1, "B": 0}

In [2]: filters = {key: (lambda x: x==value)
   ...:  for key, value in center.items()}

In [3]: filters["A"](1)
Out[3]: True

However, if I run this most simple test in an IPython notebook, I get

center = {"A": 1, "B": 0}
filters = {key: (lambda x: x==value)
           for key, value in center.items()}
print(filters["A"](1))
print(filters["B"](1))
print(filters["A"](0))
print(filters["B"](0))

gives

False
False
True
True

Apparently, in ipython notebook, the closure on value does not bind the current, but the last value of value, whereas in other python flavours, it does the opposite.

Why?

Anaphory
  • 6,045
  • 4
  • 37
  • 68
  • duplicate of, well, quite a few questions here, but http://stackoverflow.com/q/13355233/41316 is a good starting point. To make a long story short, you want `lambda x, value=value: x == value` to capture the value of `value` at lambda definition time - else it will look for the current (call time) value of `value`. – bruno desthuilliers Dec 11 '14 at 15:56
  • Thanks. I'll try to understand what I did, but it looks like it sometimes works and sometimes not, without the default argument trick. I'll give details, if I find that I'm not confusing things. – Anaphory Dec 11 '14 at 15:59
  • without the default argument trick, it will use whatever `value` is bound to **at call time** - so for at least one of the lambdas (the last created) it should _seem_ to work (unless of course you rebind `value` later on in the same scope ). – bruno desthuilliers Dec 11 '14 at 16:06
  • Bloody confirmation bias. It *seems* to behave in `ipy` and `py`, but only because, as you imply, the value for `A` is bound last, so I stopped testing. Argh. Self-Delete or Vote to Close as Duplicate? – Anaphory Dec 11 '14 at 16:07
  • Decisions, decisions... xD – bruno desthuilliers Dec 11 '14 at 16:08
  • The behaviour *was* non-deterministic, because the dict comprehension would iterate over the `center.items()` in an undefined order, and thus `value` could be either `0` or `1` afterwards. But in 3.6+, dictionaries are ordered, further complicating the example. – Karl Knechtel Aug 16 '22 at 02:15

0 Answers0