3 ms·
You can achieve the same thing in python by using two lambdas (which is actually what you're doing in JS with map): >>> powers_of_x = [(lambda i: (lambda x:
by Kwantuum 7y ago
You can achieve the same thing in python by using two lambdas (which is actually what you're doing in JS with map):
>>> powers_of_x = [(lambda i: (lambda x: x**i))(i) for i in range(10)]
>>> [f(2) for f in powers_of_x]
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
Or you can use default parameter values to use a single lambda (though this means it can be overridden, it's not semantically equivalent to the js implementation)
>>> powers_of_x = [lambda x, i=i: x**i for i in range(10)]
>>> [f(2) for f in powers_of_x]
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
your python snippet is equivalent to the following JS:
>>> function* comprehension(iterable){
>>> let i;
>>> for(let j of iterable){
>>> i = j;
>>> yield x => x**i;
>>> }
>>> }
>>> powersOfX = [...comprehension([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])];
>>> powersOfX.map(f => f(2))
[512, 512, 512, 512, 512, 512, 512, 512, 512, 512]
And Python's comprehensions are actually a shorthand for writing the above generator with this syntax: yieldExpression for i in iterable. The semantics are consistent with the regular for..in
>>> def comprehension(iterable):
>>> for i in iterable:
>>> yield lambda x: x**i
>>> [*comprehension(range(10))]
is equivalent to
>>> [lambda x: x**i for i in range(10)]
This is all a consequence of python's late binding.
- Izkata 7y agoAmusingly, the "default parameter" version relies on a feature that also gives rise to another WTPython entry: https://github.com/satwikkansal/wtfpython/blob/master/README.md#-beware-of-default-mutable-arguments https://github.com/satwikkansal/wtfpython/blob/master/README...
- sjagoe 7y agoThat's a different issue around default arguments that are mutable, rather than default arguments generally. The lambda case here is more like a default argument of a constant integer (immutable) than a default that is a list, which can be altered directly by the function it's a default of.
- Izkata 7y agoThe underlying feature that both rely on is that default arguments are set on function declaration instead of function call. Mutable/immutable only affects whether or not you hit the bug.
- mplanchard 7y agoParenthetical comprehensions (generator expressions) are equivalent to your expanded function, but list comprehensions are not. `(x for x in range(10))` creates a generator, but using square brackets converts it to a list, including allocating the necessary memory. If you’re trying to do yield and streaming, the parens will serve you better.
- Kwantuum 7y agoYou will notice that I explicitly unpacked the generator object in the brackets below the generator function by prefixing it with an asterisk.