3 ms·
> All you need is "x=x" to make a copy: Your code is illegal Python on two levels. - Lambdas in Python do not allow assignment at all. - Variables in Python
by Blikkentrekker 6y ago
> All you need is "x=x" to make a copy:
Your code is illegal Python on two levels.
- Lambdas in Python do not allow assignment at all.
- Variables in Python cannot be assigned using themselves in their r.h.s., without first being assigned something else, because Python's scoping is strange.
You serve well as an example of a programmer that does not understand Python's semantics here, because they are very counter-intuitive, and you also serve as an example of a programmer that does not understand how scope works at all, even if your example be worked into something of valid Python syntax:
thunks = []
for x in "abcd":
def thunk():
y = x
print(y, end='')
thunks.append(thunk)
for thunk in thunks:
thunk()
The output is `dddd`, not `abcd`; the `y = x` part is completely irrelevant in this case, for when the thunk is called, `x` has already been re-assigned, and so `y = x`, is assigned the new value.
Again, `x` is re-assigned on every new iteration of the loop, as such the `x` in every single one of those thunks contains the value `x` had at the last iteration of the loop when the loop completes.
There are many ways to solve this issue, such as the one I initially gave, but yours isn't one of them and that you thought it was shows the counter-intuitive nature of Python's behavior here.
> ("list" is a builtin, so not a good variable name.)
Which would be another problem with Python's lack of scope. Shadowing the names of library functions and constants is not problematic in languages with proper block scope.
- mkl 6y agoMaybe you should try running it before jumping straight to insults? My code is perfectly legal in Python and runs exactly as I said. Yours: In [1]: list = [] ...: for x in range(5): ...: list.append(lambda y: y+x) ...: [f(100) for f in list] Out[1]: [104, 104, 104, 104, 104] Mine: In [2]: list = [] ...: for x in range(5): ...: list.append(lambda y, x=x: y+x) ...: [f(100) for f in list] Out[2]: [100, 101, 102, 103, 104] I understand the semantics just fine, and it's very clear what's going on. In my version, each lambda has two parameters, one called y, and one called x. The one called x has a default value, and the default value is whatever the loop variable x's current value is: a copy is made of the loop variable's value, and stored as a default parameter value. There is no assignment, and a variable is not assigned to itself. The parameter has the same name, but the scope is different; within the lambda, the parameter shadows external variables, just as in any function. This is idiomatic Python code, taught to beginners (search for n=n - it's about this same loop thing): https://realpython.com/python-lambda/ https://realpython.com/python-lambda/ You do the same thing when passing parameters through to an inner function, like this: def outer(x, y): def inner(z, x=x): return z+x print(inner(2*y)) Shadowing list in a function scope is fine (just confusing), but your code does it in the global scope. You seem to have a bone to pick with Python for some reason, but to me your attempts at criticism fall completely flat, as they are either factually incorrect or amount to "Python is different from [language x]".
- Blikkentrekker 6y agoAh yes, mea culpa, I misread your example as lambda x: x = x; do_thing(x) Rather than the: lambda x, x = x: do_thing(x) And yes, your example works, and is functionally similar to my initial solution of using that function scope does exist by simply creating a function for no other reason than to call it to create a new scope. That doesn't stop that both examples are ugly hacks needed to solve a problem with the language that most languages do not have. And despite your calling it idiomatic, I have never seen your example in the wild and it is, frankly, simply a hack that few programmers that haven't been explicitly taught this trick would quickly see the intend behind.