Unlock Python Speed: 10 Little‑Known Tricks to Supercharge Your Code
This article reveals ten often‑overlooked Python performance techniques—from replacing range(len(...)) with enumerate to leveraging Numba, Polars, and mypyc—providing concrete code examples, profiling commands, and library recommendations that can turn sluggish scripts into lightning‑fast production pipelines.
If you work with cloud infrastructure, SRE, or data‑science pipelines, you likely love Python for its clarity, yet you may have felt its slowness. Most performance bottlenecks stem from developer choices such as inefficient data structures, unnecessary allocations, or habits carried over from other languages.
1️⃣ Stop using range(len(...)) – use enumerate
# Slow
for i in range(len(my_list)):
value = my_list[i]
# Faster and more Pythonic
for i, value in enumerate(my_list):
...Using enumerate eliminates redundant indexing and lets the interpreter optimise the loop.
2️⃣ Replace large list collections with array , deque or numpy arrays
from array import array
my_array = array('i', [1, 2, 3, 4]) # Much faster than list for intsFor numeric data, numpy or polars.Series (Rust‑based) can be up to 50‑100× faster than Pandas.
3️⃣ Accelerate pure functions with functools.lru_cache
from functools import lru_cache
@lru_cache(maxsize=128)
def expensive_computation(x, y):
...Memoisation dramatically speeds repeated calls, especially in ML pipelines.
4️⃣ Compile Python with Numba (no code changes)
from numba import jit
@jit(nopython=True)
def compute(x):
...The JIT‑compiled function can run up to 100× faster, ideal for tight loops and numeric code.
5️⃣ Use Polars instead of Pandas for large DataFrames
import polars as pl
df = pl.read_csv("data.csv")
df = df.filter(pl.col("sales") > 1000)Polars leverages Rust and native multithreading, often delivering 10× or more speedups over Pandas.
6️⃣ Profile before optimising
python -m cProfile my_script.py
# Or with line_profiler
pip install line_profiler
kernprof -l my_script.py
python -m line_profiler my_script.py.lprofProfiling reveals true bottlenecks, preventing blind optimisation.
7️⃣ Minimise attribute look‑ups in tight loops
# Bad
for _ in range(1000000):
value = my_object.some_attribute
# Better
attr = my_object.some_attribute
for _ in range(1000000):
value = attrEach attribute access triggers a dictionary lookup; caching the reference saves time.
8️⃣ Pre‑allocate lists instead of appending
# Slow
result = []
for i in range(1000000):
result.append(i)
# Faster
result = [None] * 1000000
for i in range(1000000):
result[i] = iPre‑allocation avoids repeated memory reallocations.
9️⃣ Try Pydantic V2 or msgspec for fast data validation
# Pydantic V2 (still Python‑based)
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
# msgspec – Rust‑backed, much faster
import msgspec
class User(msgspec.Struct):
id: int
name: str msgspecoutperforms both Pydantic and dataclasses.
🔟 Prefer generators over materialising large lists
def slow():
return [x**2 for x in range(10**6)]
def fast():
return (x**2 for x in range(10**6))Generators reduce memory usage from gigabytes to near‑zero.
Additional tip: compile with mypyc (experimental)
pip install mypy mypyc
mypyc my_module.pyIf your code uses type hints, mypyc can turn it into a C extension for substantial speed gains.
Most developers think Python is inherently slow, but by applying these under‑the‑radar techniques—proper data structures, JIT compilation, profiling, and modern libraries—you can shrink minutes‑long workloads to seconds without rewriting in another language.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
