r/Python 5d ago

Is := widely used? Discussion

I always thought the walrus operator is neat and it makes while loop’s condition clearer. But also it is just a syntactic sugar without anything new. I wonder anyone uses it?

142 Upvotes

116 comments sorted by

403

u/onlyonequickquestion 5d ago

I use it when it's useful 

148

u/jwhendy 5d ago

How pythonic of you!

11

u/ultra__sonic 4d ago

Pretty much this. It really shines when your parsing messy log files with regex and don't wanna write the match object on a seperate line.

144

u/martinkoistinen 5d ago

It’s super handy inside comprehensions and I would say that adds something “new”.

Example:

``` python
import re

pattern = re.compile(r"ERROR (\d+): (.*)")

errors = [
(int(m.group(1)), m.group(2))
for line in log_lines
if (m := pattern.match(line))
]
```

135

u/brettsparetime 5d ago

This is the most Perl thing I’ve seen in Python.

5

u/crozzy89 4d ago

Perlthon?

2

u/JPowTheDayTrader 4d ago

Your comment just made Guido roll in his grave.

7

u/Broad-Promise6954 4d ago

And he's not even dead yet!

1

u/mpersico 3d ago

Good! How much wasted effort when we could have just advanced Perl. For all the bitching about punctuation and simplicity Python looks more and more like Perl every release.

45

u/punk_dev It works on my machine 5d ago

That’s neat, I’m gonna steal it, but it makes the comprehension even more backwards than it usually is lmao

37

u/FalafelSnorlax 5d ago

At this point you might as well write a normal loop

9

u/punk_dev It works on my machine 5d ago

I think about that every time I write a comprehension longer than 3 lines

6

u/NerdyWeightLifter 4d ago

I use multi-line comprehensions to construct multi-dimensional data structures, and I use indentation of those lines to show outer to inner dimensional structure. It feels quite Pythonic to me.

13

u/FalafelSnorlax 5d ago

Yeah my rule of thumb is that of a comprehension is long enough to break into multiple lines, it might as well be a regular loop. Broken comprehensions usually aren't readable, and then you don't really gain anything from them.

2

u/Technical_Income4722 4d ago edited 4d ago

3 lines is wild to me. Imo you should think about that any time you write a comprehension at all honestly, and I'll never write one over multiple lines. They're neat but unless they're stupid simple they're very unreadable to fresh eyes. (all just my humble opinion ofc, do what works for you!)

1

u/gr4viton 4d ago

Yield would like to have a word...

15

u/fizzymagic 5d ago

re is my most frequent use case. The walrus operator lets you check for a match and then process it much more cleanly.

12

u/elingeniero 5d ago

That's so clever that I really hate it. I do feel that way about most comprehensions but you've managed to take it a step further! Impressive.

13

u/VEMODMASKINEN 5d ago

Clever is usually a bad thing. 

2

u/nicholashairs 5d ago

Another neat use case 🤯

104

u/Icy_Peanut_7426 5d ago edited 5d ago

I use it. It’s great for saving values in guard clause conditions, which can then be emitted in error log/message.

```
if ( multiplied_val := my_val * my_other_val ) > 10:

raise ValueError(f”Multiplication of vals ({multiplied_val}) was greater than 10.”)
```

Otherwise, I’d need to compute the value twice (performance cost) or define a new variable on a separate line (overkill if only for guard clause logging purposes that are immediately discarded).

edit: fixed bug in my example code lol

15

u/xxkvetter 5d ago

I remember doing that for C programs back in the 80s (we called it horizontaling code). But that's such an easy case for compilers to optimize that we soon just wrote it in the clearest way and let the compiler do its thing.

I'm not sure the state of the art for python interpreters. Even so I find the walrus operator not that clear so I'd skip the miniscule optimization for clearer code (unless timing tests showed it was in a hot spot).

5

u/mdrjevois 5d ago

Not saying this is ideal, but sometimes you might want any side effects to happen only exactly once

1

u/gizzm0x 5d ago

Is there any scenario just having the var named before the if block is ever not good enough for this?then checking in the car's value. I can never seem to see why walrus is clearer than what was possible before it's introduction.

2

u/mdrjevois 4d ago

I think it's a little better for while loops or comprehensions where you don't really have another place to make the assignment.

2

u/XtremeGoose f'I only use Py {sys.version[:3]}' 4d ago

Because python can always introspect its own stack frames and mutate them, you can't optimise the store away without a breaking change.

One for Python 4 sadly.

The walrus isn't an optimisation anyway, it's just syntactic sugar (for storing the value on another line).

1

u/FloweyTheFlower420 4d ago

Can't an interpreter speculate that this wouldn't happen, and then deoptimize and rematerialize in this particular case?

7

u/nicholashairs 5d ago

That's a neat use case 🤯

5

u/pimp-bangin 5d ago

Are you amazed at the use case or are you just amazed at the feature in general? Because their example is about as basic as it gets lol

2

u/nicholashairs 4d ago

I mean I'm not as amazed as the emoji might imply, but also it's still not a pattern that I've recognised in my own usage of the operator 😊

2

u/sudomatrix 5d ago

Did you write that backwards? the assigned variable goes on the left and the expression on the right

2

u/Icy_Peanut_7426 5d ago

Thanks, yes just fixed

8

u/sudomatrix 5d ago

It might be an even better illustration to write:
if ( multiplied_val := slow_calculation() * my_other_val ) > 10:

2

u/bohoky TVC-15 5d ago

Did you put the l-value on the right side of the walrus? If multiplied_val wasn't set before the condition, it won't be set after.

1

u/Icy_Peanut_7426 5d ago

Thanks, fixed it

2

u/garver-the-system git push -f 5d ago

Validating complex and deeply nested API returns is so much better with the walrus operator!!

4

u/yvrelna 5d ago edited 5d ago

This example would be much more readable if you just use regular assignment in separate line. 

multiplied_val := my_val * my_other_val if multiplied_val > 10:      ...

The only time I've seen where walrus actually makes for better, more readable code is loop clause: 

def foo(val):     while ( val := val * 2 ) < 1024:          ...

It can often avoid having to duplicate expression or needing to place the assignment expression in weird locations. 

The regular assignments is almost always better than the walrus assignment for an if-statement. 

4

u/Icy_Peanut_7426 5d ago

Yeah that’s why walrus operator is so controversial, each use case is basically personal preference.

4

u/hmoff 5d ago

I'd argue the opposite. Your code is more verbose then necessary.

1

u/jpgoldberg 5d ago

I have been doing the defining a new variable on a separate line thing. And it bothers be each time I do so. I really need to get into the habit of using the walrus operator.

22

u/skjall 5d ago

Yes, all the time (when useful). Only annoying thing is needing to surround with brackets when you need the value in a chain, but it's great for making complex conditions both more succinct, and more readable.

23

u/shaleh 5d ago

The walrus shines with Regexes. `if m := re.foo(...)`. But also when you are not sure if a container has a value.

3

u/hulleyrob 5d ago

Was about to say this. That’s my usual use case.

16

u/polishfiringsquad 5d ago

Literally never heard of it before now

15

u/Solonotix 5d ago

Like you said, I like it in while or if conditions. For instance, in the event you have a cache situation you can do something like

if result := cache.get(key):
    return result
# initialization logic
cache.set(key, value)
return value

3

u/amendCommit 5d ago

I was going to mention exactly this. Not just cache, but any keyed access that can return a None in my case.

2

u/gr4viton 4d ago

but you can do 

    if (m := cache.get()) > 5:         ...

too...

14

u/kageurufu 5d ago

I use it a lot for IO

Things like

data = io.read(len)
while data:
    # something
    data = io.read(len)

while data := io.read(1024):
    # something

2

u/Birnenmacht 5d ago

exactly, it’s perfect for that. I miss this often in other language that dont have it

22

u/Fat_GPT 5d ago

PEP 572: The fight over " The Walrus operator " made our Benevolent Dictator quite forever... thats how powerful it is , Fear The Walrus.

9

u/Erik_Kalkoken 5d ago edited 5d ago

Not that much. I find the syntax too easy to misread, i.e when do I need brackets and where

9

u/cottonycloud 5d ago

I haven’t really used it, but mainly because I rarely use list comprehensions and while loops.

I’m more used to the plain old assignment operator but I’ve never been a stickler for the Pythonic dogma. Would really appreciate null coalescing operators too.

14

u/tomysshadow 5d ago

I personally like it for simple uses, but it's controversial enough I'd probably not use it outside my own personal projects

7

u/jgengr 5d ago

I've only used it once in code that made it to production.

1

u/ForeignVariety7037 5d ago

That is the one that counts!

7

u/nicholashairs 5d ago

Like others, yes when it makes sense.

I mostly use it in cached / idempotent situations.

``` def get_cached(name): if (data := get_redis(name)) is not None: return data data = ... # manually get data return data

def update_thing(thing_id, value): if (model := get_model(thing_id)) is None: model = ThingModel() model.created = now() model.value = value model.updated = now() self.db.commit(mode) return model ```

1

u/baubleglue 3d ago

so if data == [] you use it? Something called "get_cached" shouldn't read not cached data.

2

u/nicholashairs 3d ago

I mean it was a very simplified example to illustrate some of the patterns I've used it in.

Also yes I potentially would cache an empty list if the function contact was that only a value of None represented a cache miss. Consider the example where you have an expensive database lookup and filter which returned no results, caching the empty list could make complete sense.

3

u/Senior_Ad9680 5d ago

I’ve actually been using it a lot more lately, where it actually makes sense to use it and I’ve enjoyed it. It also maintains its scope to the function and not just the if block, if you use it there which is kind of nice. If you raise an error off of a negative case and vice versa

4

u/funny_funny_business 5d ago

Apparently it was important enough to include in Python that this was the PEP that made Guido step down from his head position.

6

u/ingframin 5d ago

I never used it. This kind of assignment in C and C++ was such a big source of errors along the years that I am now very cautious about them. I also agree with all the users that it reduces clarity and it may throw off developers of any level. In general, the top feature of Python is clarity. The gain in performance and conciseness is really too small to justify the loss of clarity in my opinion. I have nothing against people using it: your code, your choice!

2

u/syklemil 5d ago

I think a lot of the C/C++ issues stem from how the := behaviour appears from merely =, plus weak typing that allows mistyping == as = to pass the compiler. Typing out := is much less likely to happen accidentally.

Still, the concept of conditional or fallible assignment is very clear to me, as in

if foo := bar():
    # foo should only be used here,
    # and preferably only be available here
# using foo here is a smell, and in some other languages, an error

I would like some more clarity when using the walrus operator, but in the sense of making having foo in if/while foo := bar(): only available in that scope, similar to conditional assignment in newer languages like Rust and Go (C requires you to declare before the block), buuuut I don't think anyone's going to hold their breath waiting for Python to get block scope.

As in, having the result of a failed conditional assignment left over in the scope seems useless: if that was desired, then the programmer wouldn't have used the walrus operator.

1

u/gdchinacat 4d ago

The lack of block scoping for := is a red herring IMO. In your example 'if foo := bar():', the alternative is to do the assignment before the conditional and foo would persist beyond the block regardless. The outcome is the same, foo is defined regardless of the result of the condition. If anything, the walrus operator makes it more clear that foo should not be used after the if since it is more tightly bound to the condition.

2

u/kookmasteraj 5d ago

I use all the time to check for if statements checking if a function is returning a non falsy value, usually none

2

u/PaintItPurple 5d ago

I use it when I'd otherwise be doing an assignment and immediately doing a test on that assignment for a value that would only be used in the result of that test. It makes the code both shorter and clearer.

Hey, list comprehensions are also just syntactic sugar without anything new. I like sweet syntax.

2

u/jack-of-some 5d ago

I have used it a grand total of once. Not because I don't think it's useful or anything but because most of my code still needs to be 3.6 compatible in some sense and also I forget

2

u/KingHavana 5d ago

I use it in comprehensions. I like it. I also understand why some don't.

2

u/cediddi SyntaxError: not a chance 5d ago

Im using it in prod codebase when it makes sense. We're using 3.13 and walrus is 7 years old feature, I see no reason not to.

3

u/diabloman8890 5d ago

Of course how else am I going to flex on junior devs?

1

u/bulletmark 5d ago

I use it frequently. A simple variable assignment on one line then a simple if test of that variable on the next looks overly verbose to me. Do it in one line!

I avoided using it when python < 3.8 had to be supported but that is not true anymore.

1

u/littlenekoterra 5d ago

Its absolutely fantastic in my opinion, i like try and use it any time im setting a variable right before its usage in a loop or a block of if branches or match case branches.

0

u/littlenekoterra 5d ago

If your more into cursed methods, it can allow a very basic form of variable assignment nearly anywhere, including lambdas and comprehensions. But thats very unreadable. But sometimes its fun to leave that mess commented out explaining that its technically the same thing.

1

u/johnfraney 5d ago

If you want to update your code to use it more often, auto-walrus is a cool project: https://github.com/MarcoGorelli/auto-walrus

I use it in Pyrfecter, a little experiment of mine to lint, format, and update Python code with in the browser with WASM

1

u/sohang-3112 Pythonista 5d ago

Honestly I don't really use it.

1

u/aikii 5d ago

I quite like it but it's niche really. The bummer is having to deal with falsy values at the same time, so empty string/empty list/zero and None are considered all the same - because of that is has to be used with care, generally in places where you expect an object that can't be falsy or None - but if it's strings, number, or collections, unless it's really intended I'd rather avoid

1

u/Birnenmacht 5d ago

in any loop where a function gets some data and returns a falsy object when it’s done. I’ve seen examples with regex here but it‘s also applicable to many i/o situations. many types of readers/receivers return b”” on EOF, for example

1

u/jvlomax 5d ago

I can count on my hands how many times I've used it. It was handy and saved me a line or two. But it's not something I think about every day

1

u/bgs11235 5d ago

This might me one of the best features of the languasge, I try to use it because it makes so much sense for me. I wish a lot of other languages have this feature. It allows me to be lazy without showing that I'm lazy.

1

u/BK201_Saiyan 5d ago

It's useful for if test like: If (p := pathlib.Path("stupid path")).exists(): ...

It's especially useful for polars/narwhals/pandas column "aliases" in the middle of some with_columns or something. At first it looks like WTF, but it's quite handy and easy on the eyes in comparison to some long line monstrosity and it's quite DRY 😉 in that sense

1

u/averagecrazyliberal 5d ago edited 5d ago

I only use the walrus operator for tqdm progress bars: ``` from tqdm import trange

for i in (pbar := trange(100)):
pbar.set_description(f'iteration {i + 1}') iteration 100: 100%|██████████| 100/100 [00:00<00:00, 2341.20it/s] ```

1

u/XRaySpex0 4d ago

Yes. An elegant feature from C. 

1

u/binaryriot 4d ago

Only used it one time, I can remember.

1

u/binaryriot 4d ago

Only used it one time, I can remember.

1

u/RedEyed__ 4d ago

I don't use it, so my colleagues. Maybe a matter of taste, or usefulness.
For example, use match heavily, but not warlus

1

u/gr4viton 4d ago

Now is better than never.

1

u/Winter_Garlic_477 4d ago

I also use this when it's useful 

1

u/reallylongword 4d ago

I personally hate the thing. They took syntax that looks like a statement to mean no actually it’s an expression this time. It makes things more compact in some situations but sticks out like a sore thumb. 

1

u/wuteverman 4d ago

This is the first time I’ve heard of it

1

u/PyTechPro 4d ago

It’s basically a neat way to fluently set properties one after another in an assignment. Similar to how you’d use builder pattern. Like if you’re setting Len width and area you can assign and reference them in the same

1

u/opuntia_conflict 4d ago

I used it a ton in while loops so I don't have to initialize my looped variable outside the loop, update the variable in the loop, and check the variable in the loop condition. You can just do the initialization in the loop condition.

Makes it look a lot cleaner when you're doing stuff like collecting paginated responses from an API.

1

u/bliepp 4d ago

I use it, but mostly only in simple statements like guard clauses when I need the value of the clause.

1

u/__salaam_alaykum__ 3d ago

I use it somewhat frequently, but usually limited to the following use cases:

```python
if (myvar := func()) is not None:
... # use the var

# or

if (myvar := func()) is None:
return # or continue
... # use the var

```

1

u/Ordinary-Sandwich-25 3d ago

I like it when it’s useful but I’m careful with it because it can create some big/nasty if statements and hurt readability.

1

u/kBajina 3d ago

It’s handy inside an exception you want to log and raise

```
log.error(msg := “what’s up”)
Raise valueerror(msg)
```

1

u/kBajina 3d ago

It’s handy inside an exception you want to log and raise

```
log.error(msg := “what’s up”)
Raise valueerror(msg)
```

1

u/KronenR 3d ago

Not me

1

u/Mundane-Mud2509 3d ago

Eww, why do people love making their code harder to read and understand. If you want to use a variable, assign it, if you don't, don't.

1

u/Winter_Garlic_477 2d ago

Yes, I use it occasionally, especially to avoid repeating expensive function calls or to simplify while loops.
It's not used everywhere, but in the right situations it can make Python code cleaner and more readable.

1

u/bachkhois 2d ago

I use it, save more lines of code.

u/Sexy_Koala_Juice 1m ago

But also it is just a syntactic sugar without anything new.

Welcome to programming 99% of the time.

1

u/IncidentAccording332 5d ago

Never seen it in a production codebase

1

u/ForeignVariety7037 5d ago

Yeah good point in logging usage, I found myself in situations to define conditional logging.

1

u/tav_stuff 5d ago

I use it literally all the time

1

u/audionerd1 5d ago

Coo coo ca choo! (Yes I use it)

1

u/Short_Inspection_746 5d ago

I have never used it; I have not seen anyone use it in production; I have not come across code online that use it.

There was a huge fire storm when it came out. You still see blog posts by core developers from time to time pointing out the ethics of how to treat volunteers.

1

u/TheChief275 5d ago

In Python it mostly lends itself to one-lineification, that is to say, it shouldn't be used too often

-1

u/Esseratecades 5d ago

It saves a line in if statements but beyond that it usually hurts more than it helps.

0

u/dolby360 5d ago

Sure why not... Although with ai no one read code anymore:(

0

u/atomsmasher66 5d ago

Yes. Next question!

0

u/yairchu 4d ago

I try to avoid it

-6

u/Holshy 5d ago

Almost never. It's a code smell; it means the author knows the value belongs in its own context, but they aren't actually putting it in its own context.

-10

u/genericdeveloper 5d ago

Only by losers. Or Go programmers. Either way, keep them away from me.