collection-layout
LayoutSplits list, tuple, dict, and set literals into one-entry-per-line layout once they overflow their width, or a dict crosses an entry-count cap.
set([x for x in xs]) builds a list, throws it away, and builds a set from it, and the reader unwinds two constructions to reach one value.
dict() reaches {}, tuple([1]) reaches (1,), and dict(alpha=1) reaches {"alpha": 1}.The brace form is emitted only where it is unambiguous. An empty set() stays a call because {} names an empty dict rather than an empty set, so set([]) reaches set() and never {}. A dict(...) call reaches the brace form only where its argument carries key-value pairs a literal or a dict comprehension can hold, leaving dict(**defaults) and dict(defaults, extra=1) as they stand.
A comprehension whose element repeats its target unchanged is spelling a copy, so [row for row in rows] reaches list(rows) and {key: value for key, value in rows} reaches dict(rows). Adding a guard or a second generator makes the comprehension do work no constructor call does, and both shapes stay as written. Where a wrapper and a copy meet, the rewrite settles in a single step, so list(row for row in rows) reaches list(rows) directly rather than passing through an intermediate comprehension. It stops short of list(list(rows)), since a doubled constructor reads no better than the comprehension it would replace. An f-string or t-string replacement field goes unvisited, so a call written inside one keeps whatever shape its author gave it.
set, dict, list, and tuple are builtins a module is free to rebind, and a rebound name no longer reaches the constructor. A module that binds any of the four to something of its own therefore holds every call to that name exactly as written, while the other three collapse as usual.
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Toggles the rule on or off. |
A bracketed literal handed to set() already spells its members, so the call gives way to the brace form and set([1, 4, 9]) reads as {1, 4, 9}.
squares = {1, 4, 9}
labels = {"alpha", "beta"}
Only the delimiters on either side of the members are rewritten, so a comment sitting among them keeps the line it describes.
A list comprehension inside set() reaches the brace form directly, and one inside list() simply loses the redundant outer call.
Where the element repeats the target unchanged, the comprehension is spelling a copy, so it collapses to the constructor it was always building.
dict(), list(), and tuple() each have an empty literal to reach, whereas set() has none and stays as written.
Unwrapping alone would leave a copying comprehension the next pass collapses, so the rewrite reaches list(rows) directly rather than through [row for row in rows].
The iterable is itself a form the constructor absorbs, so the copy and the wrapper resolve together instead of leaving an intermediate call behind.
The constructor's own brackets carry the comprehension, so the wrapping call goes and the generator's body stays as written.
Both a list and a tuple literal handed to list() reach the bracket form, so the outer call disappears and the members stay as written.
A one-member result carries the comma its grammar needs, arriving where the source lacked one and staying where the source already had it.
A dict literal handed to dict() is already the mapping, leaving the outer call nothing to build.
The comma in (only,) is grammar rather than content, so a result that is no longer a tuple leaves it behind.
The pair splits on its comma into a key and a value, so the comprehension builds the mapping in place rather than through a call.
A keyword value wrapped in grouping parentheses to span lines carries those parentheses outside its own range, so the rewrite reads the value's full extent rather than starting inside the opening one.
A module that binds list itself leaves that name pointing somewhere other than the builtin, so its calls stand while set collapses as usual.
Each two-member tuple sheds its parentheses and trades its comma for a colon, so the pair sequence reads as the mapping it was building.
A set literal handed to set() is already the set, leaving the outer call nothing to build.
An async generator is never the plain copy a constructor call spells, so the comprehension keeps its body and the wrapping set() gives way to braces.
{} names an empty dict rather than an empty set, so an empty argument reaches the bare set() call instead of a brace form.
Each keyword names a key the literal can carry directly, so dict(alpha=1) reads as {"alpha": 1}.
The element differs from the target, so the comprehension does work no constructor call would do and stays exactly as written.
Collapsing here would spell list(list(rows)), which reads no better than the comprehension it would replace, so the source stays as written.
A guard drops members and a second generator flattens two levels, so neither shape is the plain copy a constructor call would spell.
A ** unpacking names no key at all and a positional argument beside a keyword builds from two sources, so neither shape reaches a literal.
Splits list, tuple, dict, and set literals into one-entry-per-line layout once they overflow their width, or a dict crosses an entry-count cap.
Sheds a grouping parenthesis pair that binds nothing, reflowing the expression onto the line it now fits.
For per-statement opt-outs, the Suppression chapter covers the # prose: skip[simplify-comprehensions] directive, which holds every line a wrapped call spans.