swcarpentry / python-novice-inflammation

Programming with Python
http://swcarpentry.github.io/python-novice-inflammation/
Other
302 stars 780 forks source link

Why use a list to swap contents of variables? #460

Closed gcapes closed 6 years ago

gcapes commented 6 years ago

Episode 3 has this challenge

left = 'L'
right = 'R'
left, right = [right, left]

but there is no explanation as to why a list is used instead of

left, right = right, left

which gives the same result.

annefou commented 6 years ago

Yes you are right. I don't kow why a list is used!

tbekolay commented 6 years ago

A list is used because Episode 3 introduces lists. We never introduce tuples explicitly, which is what is made in left, right = right, left (it's equivalent to left, right = (right, left)). Having the right side be a list lets us avoid explaining that Python automatically makes tuples out of variables in comma separate lists.

We could consider changing it to

[left, right] = [right, left]
annefou commented 6 years ago

Thanks! Yes it could be a good idea to stick to list and follow your suggestion.

jhidding commented 6 years ago

After programming Python for 15 years, I never new lists could be used as lvalues like that. In fact it confuses me a bit. The truth is that Python syntax has special syntax for assigning to multiple values, all versions (with list, explicit or implicit tuple syntax) internally compile to the same code, meaning that no 'physical' list or tuple is involved. One of the more tricky things when learning a new language is the mental model of variables, assignments and containers. On the one hand we have:

In [1]: a = 1

In [2]: b = 2

In [3]: c = [a, b]

In [4]: c[0] = 3

In [5]: c
Out[5]: [3, 2]

In [6]: a
Out[6]: 1

But on the other hand:

In [7]: d = [c, b]

In [8]: d
Out[8]: [[3, 2], 2]

In [10]: c[0] = 7

In [11]: d
Out[11]: [[7, 2], 2]

In other words, integers are atomic and always copied, while lists are always passed by reference. I'm diverging a bit from the point of the discussion, but my point is that the mental model of a list is a very delicate thing.

We should treat the lvalue unpacking (a, b = b, a) as being special syntax having nothing to do with lists. That has the advantage of being closer to the truth and it won't confuse peoples understanding of lists.

tbekolay commented 6 years ago

@jhidding are you arguing for keeping the current snippet, which is

left, right = [right, left]

? If so, that seems reasonable to me. It's also less work than changing it :+1:

jhidding commented 6 years ago

@tbekolay No, I'm arguing that we shouldn't involve lists at all. I would leave out any brackets like @gcapes suggested; or maybe even better, leave out the exercise.

Autoplectic commented 6 years ago

Couldn't it just be described that

left, right = right, left

matches up elements and assigns them synchronously? Avoid discussion of list/tuple unpacking or assignment, since nothing like this is being done:

left,  (a, b) = right, some_pair_of_things
gcapes commented 6 years ago

I think that the best solution under the circumstances is to drop the exercise. There is no clear reason to use a list to swap the variables, but modifying the exercise as I suggested in the first comment brings up the question as to what the (modified) exercise is doing in an episode about lists.

I can submit a PR if there is approval for this suggestion?

tbekolay commented 6 years ago

I'm :+1: on dropping the exercise; any other maintainers want to weigh in?

maxim-belkin commented 6 years ago

+1 for dropping the exercise.

However, because this syntax is rather useful - shall we consider adding some sort of a Did you know? .callout box just making a note that you can swap variables with a, b = b, a?

tbekolay commented 6 years ago

However, because this syntax is rather useful - shall we consider adding some sort of a Did you know? .callout box just making a note that you can swap variables with a, b = b, a?

I feel like variable swapping is not something I do really ever in Python since making a new variable with a good name is almost always preferable. Variable swapping seemed to happen more in languages like C (because maybe you get to avoid a malloc call), and so I think the a, b = b, a thing became a bit of a meme since it's a nice, simple, obvious one-liner, whereas in C it has some weird esoteric but efficient versions. Tuple unpacking in general is useful, but very much outside the scope of this novice lesson.

Also, as per some other discussions, learning this variable swapping syntax doesn't really help someone be a better programmer, just a more knowledgeable Python-user.

maxim-belkin commented 6 years ago

ok, I'm convinced :)

gcapes commented 6 years ago

Great!