A while ago, I was also sceptical about the walrus operator, although I use assignments in expressions all the time in C++. But when I was perusing a library written Python the other day, I found five spots in which the walrus operator would make sense - eliminating one line of source code without readability suffering from it.
Python's principle is not an has never been "one way to do it". Python's principle is:
> There should be one — and preferably only one — obvious way to do it.
Which is a very, very different assertion. And there remains one — and exactly only one — obvious way to do an assignment, because the walrus operator is literally invalid syntax as a statement:
That principle was bullshit anyway. There have always been multiple ways to do things, the one way was just whatever the elder Pythonista deemed to be pythonic that day.
Not true. The language optimizes for the way it is intended to be used, and changes remain sensitive to those optimizations.
"Pythonic" means intended usage, and "unPythonic" is shorthand for "you found another way to do it that kinda does what you want but (is ten times as slow/takes up ten times as much memory/doesn't work for edge-cases/has more unintentional side-effects) because it wasn't the intended usage, which is fine for your own personal projects, but please don't bring that into my code base, and pretty please don't teach other people to do it that way..."
In my work we have code in many places along the lines of:
data = expensive_function(blah, blah_blah)
if data:
# many lines of processing
data = expensive_function(blah, blah_bah)
And seen a lot of times where newcomers forget the assingment at the end that makes everything move. So yeah, the walrus version would be a lot simpler:
while data := expensive_function(blah, blah_blah):
# process data
This is just one of the "edge cases" where the walrus makes sense.
So the question is if += and sort are both "in-place", why does one throw and the other doesn't? Clearly "in-place" is not the full explanation here.
I think the real explanation is that with += there are two steps:
1- The existing list gets modified. This is fine since lists are mutable.
2- The tuple's reference to the list gets updated (even though this update is unnecessary since the list object's identity is the same).
The exception occurs at step 2, but this step is otherwise a no-op. Whether mutating a reference to the same value it already had is an actual mutation is an interesting semantics debate.
Tuples are immutable, but that doesn't mean they can't contain references to mutable objects.
When you want to use a tuple as a key in a dictionary, Python checks if all members of the tuple are immutable. If one or more of them aren't, you'll get an 'unhashable type' error.
Those small SMD resistors come on a reel, and they're typically much cheaper than 2 cent: more like 0.1 cent. Still, that's $1000 for one million units.