Fair point. It won’t magically fix concurrency. Two threads can still race to the same ??=.
But it closes the tiny window between the check and the assign that the manual if version leaves open. That’s all. For real safety, you’d still need a lock.
Without atomicity, two threads could both see None and both compute expensive_default(), wasting CPU. Worse, if default has side effects (logging, state change), they could happen twice unexpectedly.
With ??=, only the first thread computes the default; the second sees the value already set. That’s the value.
+= always performs the read-modify-write, regardless of the current value. It doesn’t need to be atomic because the operation itself doesn’t change based on a condition.
??=only writes if the current value is None. The atomicity ensures that two racing threads don’t both see None and then both compute/assign the default. That prevents duplicate work.
Under the GIL, it’s still valuable (prevents double computation in rare but real races). Under a free‑threading build, the bytecode would need proper locking to preserve the same semantics – but that’s an implementation detail. The language semantics define it as atomic; implementations must follow.
It sounds to me like having ??= be atomic is only going to confuse people, given that other operators like += are not. People who are using threads are going to have to learn to think about atomicity anyway, so why is having one operator be atomic better than having a consistent picture that’s easier to learn?
But a += 1 will not leave a with the correct value if two threads run the code at the same time. That is not different from test and set for ??= in principle. Both are race conditions that lead to the wrong answer.
The atomicity argument adds complexity and raises consistency questions without enough real-world benefit. I’ll drop it from the proposal.
??= remains as pure syntactic sugar for if x is None: x = default, with no atomicity guarantee. That keeps it consistent with += and other augmented assignments.
Thanks for the push — the proposal is stronger without this claim.
Question - are you using an LLM to create your responses? The discussion feels frustratingly like debating with an LLM, rather than with a person who has thought through their proposal and is willing to defend it because they believe it’s correct.
Yeah, it doesn’t have.
But the value of these operators is to be simple and clear.
And my speed - my first language isn’t English, so I should spend more time than you to understand your opinions, and sometimes use LLM to make my opinion clearer.
But I promise, ideas are mine.
You’re right about the timing. I had already thought through that response.
I do use tools to help with phrasing sometimes, but I’m not going to keep defending how I write. Let’s focus on the proposal — do you have any technical feedback on ?? and ??=?
Given that you’ve abandoned atomicity, this thread doesn’t seem to add anything new, and as @cdce8p is already preparing a PEP, I don’t think there’s anything more worth discussing here.
Thank you for your time.
But I still think it’s a useful design.
I really want it to join Python, even though it’s already without atomicity.
You’re right.