| name | python |
| description | Language-specific super-code guidelines for python. |
| risk | safe |
| source | community |
| date_added | 2026-06-16 |
Python: Idiomatic Efficiency Reference
Table of Contents
- Comprehensions & Generators
- Unpacking & Destructuring
- Built-ins & stdlib
- Functions & Defaults
- Classes & Dataclasses
- Error Handling
- Type Hints
- Anti-patterns specific to Python
1. Comprehensions & Generators {#comprehensions}
result = []
for item in items:
if item.active:
result.append(item.name.upper())
result = [item.name.upper() for item in items if item.active]
d = {}
for k, v in pairs:
d[k] = v
d = dict(pairs)
d = {k: v for k, v in pairs}
total = sum(list(x * 2 for x in nums))
total = sum(x * 2 for x in nums)
Use generator expressions (not list comprehensions) when the result is consumed once and not stored.
2. Unpacking & Destructuring {#unpacking}
first = items[0]
rest = items[1:]
first, *rest = items
tmp = a
a = b
b = tmp
a, b = b, a
for i in range(len(items)):
print(i, items[i])
for i, item in enumerate(items):
print(i, item)
for i in range(len(a)):
process(a[i], b[i])
for x, y in zip(a, b):
process(x, y)
3. Built-ins & stdlib {#builtins}
max_val = items[0]
for item in items[1:]:
if item > max_val:
max_val = item
max_val = max(items)
from collections import defaultdict
groups = defaultdict(list)
for item in items:
groups[item.category].append(item)
if key in d:
val = d[key]
else:
val = default
val = d.get(key, default)
counts = {}
for item in items:
counts[item] = counts.get(item, 0) + 1
from collections import Counter
counts = Counter(items)
Use itertools (chain, islice, groupby, product) before writing nested loops for combinatorial or streaming logic.
4. Functions & Defaults {#functions}
def append_to(item, lst=[]):
lst.append(item)
return lst
def append_to(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
create_user("Alice", True, False, 30)
create_user("Alice", is_admin=True, is_active=False, age=30)
def process_and_save(data):
...
def _transform(data): ...
def _save(record): ...
def process_and_save(data): _save(_transform(data))
5. Classes & Dataclasses {#classes}
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
class MathUtils:
@staticmethod
def add(a, b): return a + b
def add(a, b): return a + b
Use @dataclass(frozen=True) for immutable value objects. Use NamedTuple when you need tuple unpacking.
6. Error Handling {#errors}
try:
risky()
except:
pass
try:
risky()
except ValueError as e:
logger.warning("Invalid value: %s", e)
if os.path.exists(path):
with open(path) as f:
data = f.read()
try:
with open(path) as f:
data = f.read()
except FileNotFoundError:
data = None
except Exception as e:
raise e
except Exception:
raise
7. Type Hints {#types}
from typing import Optional, Union
def f(x: Optional[int]) -> Union[str, None]: ...
def f(x: int | None) -> str | None: ...
from typing import Any
def first(lst: list[Any]) -> Any: ...
from typing import TypeVar
T = TypeVar("T")
def first(lst: list[T]) -> T: ...
Don't add type hints to every local variable — annotate function signatures and class fields; leave obvious locals inferred.
8. Anti-patterns specific to Python {#antipatterns}
| Anti-pattern | Preferred |
|---|
len(lst) == 0 | not lst |
if x == True: | if x: |
if x == None: | if x is None: |
range(len(lst)) for iteration | enumerate(lst) |
| String concatenation in a loop | "".join(parts) |
import * | explicit imports |
Catching Exception to log and re-raise | bare raise or let it propagate |
print() for debug output | logging.debug() |
os.path.join (Python 3.4+) | pathlib.Path / "subpath" |
Manual __eq__ + __hash__ on value objects | @dataclass(eq=True, frozen=True) |
Limitations
- These are language-specific guidelines and do not cover overall architectural decisions.
- Over-compression might reduce readability; apply judgement.