You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Avoid construction of objects in comprehensions without targets #151907
For context, I ended up in a discussion about whether code like the following is a good idea:
[thread.join() forthreadinthreads]
Some people like the brevity over an explicit loop. The primary argument against this pattern is that this has the additional overhead of creating an additional list object (or set object for set comprehensions, dict for dict comprehensions). That made me wonder whether it was possible to simply omit the construction when the comprehension isn't used as a value. I managed to come up with a relatively small patch.
To be clear, I don't think this should be interpreted as an endorsement of this pattern. I, and probably many others, believe that for thread in threads: thread.join() is the better option, but that's beside the point; there are definitely people who do this in practice, and I think they'll enjoy the minor speedup.
This breaks the simple rule that an expression statement evaluates the expression to a value and tosses it or prints it depending on the input mode.
I wouldn't go as far to say that's a "rule" -- we do this kind of optimization for constants already. A blank 42 with no target is optimized away at compile-time (and I'd think there are significantly fewer people doing this than people using the comprehension pattern).
Why only for list comps and not set comps? Or for other side-effect only expressions? This will like confuse people.
I tried doing this for set/dict comprehensions as well, but it ended up breaking things because hash was no longer called on the elements.
I think we should optimize other ones as well, but this one stuck out to me because people are actually doing this in practice. I can't think of a time where we've rejected an optimization on the basis that "there are similar things that aren't optimized yet".
I would be very surprised if anyone actually noticed the difference, and if they actually cared. I've only ever seen people do a bare list comprehension in the wild, and that's a small minority already. I'd be shocked if that small minority were to also do this for sets or dicts, and then look at the bytecode for inconsistencies. People just don't look at bytecode disassembly and compare random expressions.
The explicit loop is one character shorter.
I think the appeal is that it's all on one line, but that's beside the point; people are doing this anyway.
To me it is, and at least some people will interpret this as so and even teach it as something to do.
I doubt this optimization will actually sway opinions. The people who were doing this already will continue doing this, and the people who weren't will continue to not. People care more about the aesthetics than the speed, but I just think that CPython should be aware of both cases when optimizing.
More generally, I don't think we should only optimize things that we consider "good practice". We should aim to produce fast results, even if the code to produce those results was bad.
Activity
terryjreedy commentedon Jun 22, 2026
This breaks the simple rule that an expression statement evaluates the expression to a value and tosses it or prints it depending on the input mode.
Why only for list comps and not set comps? Or for other side-effect only expressions? This will like confuse people.
The explicit loop is one character shorter. People are typing an extra character to misuse an expression.
To me it is, and at least some people will interpret this as so and even teach it as something to do.
ZeroIntensity commentedon Jun 22, 2026
I wouldn't go as far to say that's a "rule" -- we do this kind of optimization for constants already. A blank
42with no target is optimized away at compile-time (and I'd think there are significantly fewer people doing this than people using the comprehension pattern).hashwas no longer called on the elements.I think the appeal is that it's all on one line, but that's beside the point; people are doing this anyway.
I doubt this optimization will actually sway opinions. The people who were doing this already will continue doing this, and the people who weren't will continue to not. People care more about the aesthetics than the speed, but I just think that CPython should be aware of both cases when optimizing.
More generally, I don't think we should only optimize things that we consider "good practice". We should aim to produce fast results, even if the code to produce those results was bad.
gh-151907: Avoid creating temporary objects in some list comprehensio…
pythongh-151907: Reduce duplication in codegen comprehension functions
gh-151907: Reduce duplication in codegen comprehension functions (GH-…