1. 47

  2. 17


    # Handle a matched regex
    if (match := pattern.search(data)) is not None:
        # Do something with match
    # A loop that can't be trivially rewritten using 2-arg iter()
    while chunk := file.read(8192):
    # Reuse a value that's expensive to compute
    [y := f(x), y**2, y**3]
    # Share a subexpression between a comprehension filter clause and its output
    filtered_data = [y for x in data if (y := f(x)) is not None]
    1. 9

      I missed this whole debate over the summer, so thanks for posting the summary.

      I’ve hit #1 and #4 more times than I can count. I didn’t consider #2 a problem, but there’s a lot of code I’ve written that would be affected by that.

      #1 and #2 look good to me. #4 makes me skip a beat. Maybe I could get used to it. But I sorta don’t like how #3 and #4 mix “declarative vs. imperative”. They are mixing models. It would be nicer for a language to have dataflow or lazy evaluation / caching rather than having the programmer force evaluation and binding. (Although I realize Python is not this language for several reasons.)

      Over time I’ve found myself using list comprehensions only for the simplest of cases. A plain “for loop” in Python is general, powerful, and easy to write :) It stands up better to editing and debugging, e.g. to add a print statement.

      Anyway, it’s an interesting issue in language design.

      1. 4

        Sometimes list comprehensions are more elegant looking. I use them a lot because I heard a rumor they are faster than extending a list with a for loop. However this may be just wrong gossip.

        In response to @modusjonens

        s1 = """y =[]
        for x in range(1000):
            y += [x**2]"""
        s2 = """y = [x**2 for x in range(1000)]"""
        import timeit
        s1_times = [timeit.timeit(s1, number=1000) for n in range(50)]
        s2_times = [timeit.timeit(s2, number=1000) for n in range(50)]
        import numpy as np
        # -> 0.4136016632785322
        np.mean(s1_times) - np.mean(s2_times)
        #-> 0.059135758097691005
        import scipy.stats as ss
        ss.ttest_ind(s1_times, s2_times)
        # -> Ttest_indResult(statistic=7.744078660754616, pvalue=8.882270186123814e-12)

        ever so slightly better in the simplest case …

        1. 1

          Could be a fun exercise to craft some examples using both methods, profile the code, and present the results!

      2. 3

        I added these examples to the article as well, they do add some good context.

      3. 8

        Honestly, this seems like such a moderately useful feature for the price of complicating the language. I don’t think it was worth burning out Guido over this.

        But I guess he got tired of saying no, so now we have an entity multiplied beyond necessity.

        I like when software leaders say no. It’s the only way to prevent an eventual C++ situation. I am a little afraid that the next thing people will want is one-liner try-except statements, (e.g. something like y = f(x) except Foo: z or something like that), which is another thing that Guido kept saying “no” to.

        Python is supposed to be prefer to be more verbose sometimes because one-liners can easily get too hard to read. The extra newlines and indentation in trivial try-except clauses should remain.

        1. 16

          Hm? I’m pretty sure it was the opposite – Guido wanted it and there were a bunch of vocal people trying to keep it out of the language. He is of course the BFDL so it was included, but he got burnt out by the process. That’s my understanding.

          1. 7

            Oh, do I have it all wrong?

            In that case, I hope those who remain say “no” more often.

            1. 2

              The issue is that there are already many ways to solve the problems that this aims to solve, and this change is going to be hard to explain to people when teaching the language :/

            2. 1

              Honestly, this seems like such a moderately useful feature for the price of complicating the language. I don’t think it was worth burning out Guido over this. But I guess he got tired of saying no, so now we have an entity multiplied beyond necessity.

              I don’t think I agree. I think the council will actually do what you want and will, by virtue of having a multiplicity of personalities and opinions be the gating factor, say “yes” less often.

              The idea of the BDFL is a charming and attractive one, but in practice isn’t sustainable with any kind of exponential growth like what Python has been experiencing.

              1. 1

                As long as people keep saying “no” by default, I think I’ll be happy.

              2. -1

                So much :’(

              3. 13

                I always thought that as should be reused here: if foo.bar() as x: , which seemed to provide appropriate symmetry with the with statement, that solves a similar binding problem.

                Regardless of the bike shed color, though, I used to wish for this everyday for years, so I am glad it finally came!

                1. 8

                  That would introduce ambiguity in the normal with statement. Now with x as y: could be a simple assignment or could be creation of a context manager. Instead with the new syntax

                  with y := f(x) as z:

                  we have that y would be assigned f(x) and z would be assigned y.__enter__() (I think… well, I hope).


                  1. 4

                    Serious question: If using a with statement, whose job it is to manage the context manager, why do you actually need anything more than what z is, generally speaking?

                    Additionally, I had to stop and really think about what with y := f(x) as z: is doing.

                    That link also says the following:

                    To the contrary, the assignment expression does not belong to the if or while that starts the line …

                    I disagree. In the same way that the with statement owns the result of whatever.__enter__(), the if statement owns the result when evaluating the conditional in a boolean context. But, perhaps that means the as z should then provide the boolean value, which is useless given, the branch taken implies it.

                    I don’t have a horse in this race, as I haven’t seriously done Python in 6 years or more. I’m happy they’ve made a change.

                  2. 3

                    Very disappointing to see Lobsters replicating this style of comment from HN and voting it right to the top. The top response to a post like this should not be bikeshedding syntax.

                    1. 6

                      Wholehearted agreement. I’ve noticed that as the lobsters community has grown, its focus has shifted much farther off-center with a growing noise-to-signal ratio, including the stories, not just the comments.

                      1. 2

                        I am not sure what type of discussion you are looking for on an article like this, and even praise posts: “great feature addition!” “Woohoo! Pat everyone on the back!” have the potential to get bike sheddy.

                        “Uhh, it’s not a feature, it’s a backwards incompatible language change!”

                        “Why are you praising this? It’s obviously a horrible idea!”

                        “Patting someone on the back is offensive! Instead, you should send a donation to the PSF to ensure developers are compensated for these kinds of changes, to say thanks.”

                        Further, to get really really meta here, I don’t like the color you are painting my comment. My comment offered a statement of my surprise and then specifically said: “no matter! I am glad the feature now exists!”

                        I hoped for a reply that summed up the argument for doing it the way it was done, since the article doesn’t do so—received one, and then asked a follow on because I still don’t see a solid reason to introduce := over as. Feel free to downvote that part of the thread as troll, because you could certainly read it that way.

                        Lastly, I really dislike these bike shed comments about the Lobsters community in comparison to HN. There are social rules in place here, and facilities for ensuring discussion is on topic and useful. Obviously, a number of community members agreed with my sentiment and voted it up. Perhaps these folks were an elite squad of programming language designers… but, they are the community we have, so…

                        1. 2

                          I don’t have a problem with your comment, I have a problem with people just upvoting easy to consume content. That’s a criticism of the way upvotes work (I think they should probably require a reason, just like downvotes: insightful, correction, helpful, etc. as options), a criticism of the site, not a criticism of you. I apologise that I didn’t convey that in my comment.

                          1. 1

                            In a way, it may not be your comment so much as the attention it gets. Having a variety of voices in a community is important and your opinion is valid. Whether it should be head and shoulders above other comments might be more of the issue. It gives an impression of authority and undercuts other comments. (I.e., what this person says must be important because so many people agree with them and what this other person says must not be important because no one has agreed with them.)

                            Up-voting and down-voting aren’t terrible because they do provide a way to scan through lots of comments and articles, but the game changes when the audience grows.

                          2. 1

                            I totally agree. There have been a number of changes, both proposed and accepted to Python that made me say “Enh? REALLY?” but this one is not among them.

                        2. 7

                          If := has been called by Pascal and Ada the assignment operator …. Keep calling it that! …. Walrus operator makes the industry appear juvenile and unprofessional.

                          1. 8

                            Come write Puppet, we have a spaceship operator

                            1. 9

                              I think Rust’s “turbofish” (”::<>”) takes the cake for odd operator names.

                              I don’t really like the name “walrus” for “:=”, but not because it’s “unprofessional”; rather, because—as @tenken noted—it’s already widely used and generally called “assignment”, and so inventing a new name for it violates the principle of least surprise.

                              1. 5

                                The issue is, Python already has an assignment operator.

                              2. 3

                                So does C++20

                                1. 3

                                  PHP too

                                  1. 1

                                    Well, that’s my one argument for Puppet gone

                                2. 6

                                  that’s only unprofessional in the pejorative sense of “professional”. nothing about giving operators cute names affects actual professionalism (treating employees and customers with respect, honouring commitments, delivering a quality product)

                                  1. 1

                                    Part of being professional is appearing to be professional. Visible, conscious professionalism is a bit part of attaining and maintaining the trust and respect of the public for other professions. If programmers want to be treated as a profession (and the way people react to any kind of management being applied to them suggests that they do want to be treated like professionals) then they need to attain and maintain the trust and respect of the public and the business community as being professional enough to be professionals.

                                    Lawyers don’t wear suits because they love wearing suits, or because they’ve always worn suits. They wear suits because suits convey an image of professionalism that they public expects of lawyers. Lawyers are given a huge amount of trust by the public, and so they need to be trusted by the public. Not only are they self-regulating, but they frequently handle huge amounts of money, on behalf of not just big businesses but also members of the public, small business owners, etc.

                                    Programmers aren’t regulated at all, but they probably should be. They’ll oppose any attempts any anything other than self-regulation quite forcefully, and self-regulation means you need to be seen to be professional and trusted by the public. Programmers handle huge amounts of personal information. People need to feel comfortable that the people doing so aren’t cowboys.

                                    1. 3

                                      I don’t want programming to be regulated, and I deliberately want cute, unprofessional names like “walrus operator” to continue to exist in programming language communities. Professionalism be damned.

                                      1. 1

                                        Programming will be regulated. It’ll happen. It’s a question of whether programmers will be self-regulated or regulated by others, not whether they’ll be regulated eventually.

                                        ‘Walrus operator’ has to be especially stupid given it’s neither funny nor cute, already has another name, and looks nothing like a walrus.

                                        1. 2

                                          Let it be regulated by others then, rather than ourselves. An “other” is someone groups can coordinate to fight against.

                                  2. 3

                                    You would love perl5’s goatse operator: =()=.

                                    1. 2

                                      Well I should report you to your employer for your specieist bigotry and unprofessionalism.

                                      But hey, python is wide open after all. Fork your own and call it professional python and serious business operator.

                                    2. 2

                                      I remember that inability to assign in if/while was one of my biggest frustrations with Python when I first started to learn it in 2003. This is useful feature, but := is commonly associated with “imperative assignment”; however assignment in “if” is usually used as “binding” rather than “overwriting of variable”, similar to if-let in lisps. as keyword, like in with has this “binding” meaning.

                                      1. 0

                                        This makes me all kinds of :’(

                                        1. 1

                                          Hopefully it can be pre-hooked so that no one can commit with this statement present in the git repo ;)

                                          1. 4

                                            I don’t think this warrants such extreme measures, but: it probably has it’s own node type when parsed through ast.parse, so, it’s pretty easy to write a script and use as a hook on pre-commit. I wrote one of those to disallow importing a specific lib without aliasing and OS checking in a project, and as long as you only check for changed files, it’s pretty fast, too.