0

I'm trying to construct a function in Python that accepts a list of numbers and returns a list of functions dependent on the input values:

filters = lambda ys: [lambda x: x % y == 0 for y in ys]

If I call the above filters function with a list of values, it should return a list of lambda functions which have been constructed from the input list. For example, calling filters([3,5]) should return

[lambda x: x % 3 == 0,
 lambda x: x % 5 == 0]

Defining another function, applyToNum (similar to map) as

applyToNum = lambda x, fns: [fn(x) for fn in fns]

I now encounter the following behaviour:

applyToNum(15, filters([3,4,5]))     

# returns [True, True, True] rather than [True, False, True]

The interesting thing is that if I construct the filters function list manually, it works as expected:

filters2 = [
  lambda x: x % 3 == 0,
  lambda x: x % 4 == 0,
  lambda x: x % 5 == 0]

applyToNum(15, filters2)

# returns [True, False, True]

Could someone explain why the above behaviour is seen?

zenofsahil
  • 1,713
  • 2
  • 16
  • 18
  • 2
    Python closures are late binding; `y` is not evaluated until the lamba(s) are called, at which point the value on the stack is the final iteratee value from `ys` – Moses Koledoye May 07 '17 at 21:31
  • That explains it. Thank you! – zenofsahil May 07 '17 at 21:45
  • By the way, you could fix this with code like this: `filters = lambda ys: [(lambda y: lambda x: x % y == 0)(y) for y in ys]`, or this might be easier to read: `def filter_func(y): return lambda x: x % y == 0`; `filters = lambda ys: [filter_func(y) for y in ys]` – Matthias Fripp May 11 '17 at 22:27
  • Nice idea! Thanks. – zenofsahil May 13 '17 at 04:26

0 Answers0