back to indexThe most controversial Python feature | Walrus operator
Chapters
0:0 Walrus operator
1:26 Use cases
3:33 Criticisms
5:59 Guido van Rossum
00:00:00.000 |
This is the walrus operator, and this is the assignment expression that it enables. 00:00:05.600 |
It's been added as a feature to Python 3.8 after a whole lot of drama. Majority of Python core 00:00:12.720 |
developers, as far as I can tell, were against it, and the drama and toxicity over it drove Guido van 00:00:19.120 |
Rossum, creator of Python, to step down from his leadership role of benevolent dictator for life 00:00:25.200 |
after he accepted the walrus operator as part of the PEP 572 proposal. So what is it? First, 00:00:32.320 |
let's talk about the assignment statement, the equal sign in Python. We can thank Fortran for 00:00:39.760 |
this, I think, not very good design decision of using the equal sign for assignment. So assigning, 00:00:47.440 |
in this case, 42 to the variable x. Most programming languages use it, with a few exceptions. 00:00:53.360 |
Pascal uses the walrus operator for assignment, and R uses a different operator. This goes against 00:01:01.200 |
the notation of mathematics, where the equal sign is used to designate equality. But there's a 00:01:07.040 |
lesson here, I think, that even bad design decisions, once accepted and once we get used to them, 00:01:11.680 |
aren't so bad. It's all about consistency. So the assignment expression does a little bit more. It 00:01:17.920 |
also signs 42 to x, performs the assignment operation, but as an expression, it returns 00:01:24.160 |
the value that it assigned as well. This can be useful in a lot of contexts. Let me talk about the 00:01:29.280 |
cases where I find them particularly useful. So I use regular expressions a lot as part of data 00:01:34.960 |
science to clean up and organize data. So a common piece of code you might see is you perform a 00:01:40.080 |
regular expression match, returning it to a variable like res here, that contains the regular 00:01:46.960 |
expression object if a match was found, and contains none if no match was found. And then 00:01:52.160 |
you have some kind of conditional, like an if statement, that checks whether a match was found. 00:01:56.560 |
And if it has been found, then you do something with the regular expression object. In Python 3.8, 00:02:01.680 |
all that gets combined into a single line that performs the match operation, assigns the result 00:02:08.880 |
of the match to res, and then check if res contains a regular expression object. A similar use case 00:02:15.360 |
is in reading files. There's a lot of ways to read a file, but a lower level version, there's 00:02:20.080 |
usually a while loop. Then there's a read operation that's stored in the chunk variable or something 00:02:24.880 |
like that. And then there's a condition that checks whether the chunk contains anything, 00:02:28.320 |
or if an end of file was reached, at which point you break out of the while loop. If it has not 00:02:32.960 |
been reached, then you do something with the data that was fetched. In Python 3.8, this gets 00:02:38.160 |
compressed into a single line that performs the read operation, the assignment of the fetched data 00:02:43.600 |
to the variable chunk, and then the conditional check in the while loop of whether chunk returned 00:02:48.800 |
any data or if the end of the file was reached. To me, this is elegant. Other use cases in list 00:02:54.560 |
comprehensions, you can share sub-expressions. Like in the filter, you can assign f of x to y, 00:03:00.720 |
and then reuse that y in the output of the comprehension. You can also, in a list, 00:03:06.000 |
reuse a value. For example, if it's expensive to compute, so you can compute f of x once, 00:03:11.280 |
assign it to y, and then reuse y in the rest of the list definition. As a side note, I don't like 00:03:16.640 |
to use chained assignments, but chain assignments have the same feature that the function f is only 00:03:22.640 |
computed once. So this particular statement here is equivalent to computing f once, assigning it 00:03:28.320 |
to a temp variable, and then assigning that temp variable to both x and y. There are quite a few 00:03:34.160 |
criticisms that are both objective and subjective that talk about the complexities of programming 00:03:40.560 |
language design and human nature in general. So first is the idea that both the equal sign and 00:03:46.800 |
the walrus operator perform an assignment, so it might be confusing to beginners. I'm not sure about 00:03:52.320 |
the history of PEP 572, but my guess is that this criticism was more prevalent before the exception 00:03:58.800 |
was added. That assignment expressions can't be on a line standalone by themselves without using 00:04:04.160 |
parentheses. I think this clarifies to beginners that assignment expressions should not be used 00:04:09.280 |
as an assignment statement. There's a set of principles defined in PEP 20, otherwise called 00:04:14.560 |
"Design of Python" that has some ideas to aspire to in the design of Python. Just like Guido said, 00:04:20.800 |
some of these are subjective, and I think they are ideas to aspire to as opposed to perfectly 00:04:26.720 |
implement because they're overlapping and there's a natural tension between them. So the first 00:04:31.600 |
principle that's been brought up is there should be only one obvious way to do it, and some people 00:04:36.560 |
argued that the walrus operator performs an operation that already had another way to do 00:04:42.320 |
the same exact thing. I've also heard a funny kind of criticism that the equals operator 00:04:46.960 |
worked like an assignment expression in C, and it kind of sucked in C, or at least was error-prone. 00:04:53.520 |
So there you go, you have a case study in the real world where this kind of operator being used to 00:04:58.240 |
designate an assignment expression was error-prone. Another "Design of Python" principle that people 00:05:03.680 |
brought up is that simple is better than complex, and while it seems that the assignment expression 00:05:10.160 |
makes the code simpler, in fact, it was argued that it was only reducing white space and was 00:05:15.760 |
in fact adding complexity, or at least moving the complexity. Finally, the criticism that applies 00:05:22.080 |
often in programming language design is that not enough testing was done on how actual developers 00:05:27.520 |
will use it. I think that's probably the biggest challenge of programming language design, and 00:05:32.240 |
design in general, is you don't know how people, how thousands or millions of developers are going 00:05:37.200 |
to use this feature once it's in the wild, and how other features will interact with it when it's in 00:05:42.960 |
the wild. So this criticism is certainly true, but I think it is always true. My own feelings about 00:05:49.440 |
the walrus operators, I think when used properly, it's quite elegant and even beautiful, but it also 00:05:57.440 |
represents more than that. To me, it represents the importance of leadership in a community of 00:06:02.320 |
smart people that disagree. So this is the feature that led Guido to resign, and I spoke with him on 00:06:08.240 |
the podcast that I host, and I'll speak to him again. I think he's one of the most brilliant 00:06:13.600 |
language designers and programmers we have, also a great leader in the software engineering community. 00:06:18.720 |
So this is a little excerpt from a post he made. It reads, "Now that PEP 572 is done, 00:06:25.200 |
I don't ever want to have to fight so hard for a PEP and find that so many people despise my 00:06:30.320 |
decisions. I would like to remove myself entirely from the decision process. I'm basically giving 00:06:36.080 |
myself a permanent vacation from being BDFL, and you all will be on your own. So what are you all 00:06:43.760 |
going to do? Create a democracy? Anarchy? A dictatorship? A federation?" So to me, the walrus 00:06:52.240 |
operator represents more than just assignment expressions. It represents the power of 00:06:56.720 |
leadership to break through a toxic stalemate. I think leaders have to make difficult decisions, 00:07:04.640 |
sometimes unpopular decisions, and sometimes ones, if you look at the long arc of history, 00:07:12.320 |
prove out to be bad decisions. But without leadership, I think we can't make progress. So 00:07:19.680 |
the messiness, the chaos of democracy, is that the divisiveness can be paralyzing. 00:07:26.240 |
And we need leaders to inspire us, to guide us, and to make difficult, risky decisions. 00:07:34.560 |
So to me, the walrus operator would be useful for regular expressions, but it will also be a 00:07:40.480 |
reminder of the importance of leadership in the programming world and in our world in general. 00:07:47.280 |
If you enjoy these short little videos, subscribe, and remember, try to learn something new every day.