10 Python Tricks That Senior Developers Actually Use Every Day

Why These Tricks Matter

If you have been writing Python for a while, you have probably picked up a few habits along the way. But there is a difference between code that works and code that senior developers actually reach for when they are solving real problems. These tricks are not party tricks - they are battle-tested techniques that show up again and again in production codebases, code reviews, and open-source projects.

Let us dive into 10 Python tricks that senior developers use every day.

1. Use Walrus Operator for Cleaner Assignments

The walrus operator, introduced in Python 3.8, lets you assign and return a value at the same time. This eliminates redundant calls and makes your code more compact.

# Before (redundant function call)
result = calculate()
if result > 0:
    print(result)

# After (walrus operator)
if (result := calculate()) > 0:
    print(result)

This is especially useful in list comprehensions and while loops where you need to reference a value multiple times.

2. Leverage defaultdict for Cleaner Data Structures

Instead of checking if a key exists before appending, use collections.defaultdict:

from collections import defaultdict

groups = defaultdict(list)
for item in data:
    groups[item.category].append(item)

# No need to check: groups[key] always returns a list

This pattern is incredibly common in grouping, counting, and caching scenarios.

3. Use enumerate() Instead of Manual Counter

Stop incrementing a counter manually. enumerate() gives you both the index and the value:

# Avoid this
i = 0
for item in items:
    print(i, item)
    i += 1

# Do this instead
for i, item in enumerate(items):
    print(i, item)

You can also start the index from any number: enumerate(items, start=1).

4. Chain Comparisons for Readability

Python allows you to chain comparison operators, which makes numeric range checks elegant and readable:

# Verbose
if x > 0 and x < 10:
    pass

# Clean
if 0 < x < 10:
    pass

You can chain as many comparisons as you need. It is not just readable - it also evaluates x only once.

5. Use dataclasses for Structured Data

Stop writing verbose __init__ methods for simple data containers. dataclasses generate them automatically:

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float
    label: str = "unnamed"

p = Point(1.0, 2.0)
print(p)

With frozen=True, you get immutable objects perfect for configuration and DTOs.

6. Merge Dictionaries with | and |=

Python 3.9+ introduced dictionary merge operators:

base = {"host": "localhost", "port": 8080}
overrides = {"port": 9000, "debug": True}
config = base | overrides
# {"host": "localhost", "port": 9000, "debug": True}
base |= overrides

No more {**base, **overrides} unpacking gymnastics needed.

7. Use __slots__ for Memory-Efficient Classes

When you create many instances of a class, __slots__ can cut memory usage by 40-50 percent:

class Point:
    __slots__ = ("x", "y")
    def __init__(self, x, y):
        self.x = x
        self.y = y

By restricting attribute creation, Python stores attributes in a compact array instead of a dictionary. Use this for performance-critical code with many objects.

8. contextlib for Clean Resource Management

Stop writing try/finally blocks for simple cleanup. Use contextlib utilities:

from contextlib import contextmanager, suppress

@contextmanager
def timer():
    start = time.time()
    yield
    print("Took", time.time() - start, "s")

with suppress(FileNotFoundError):
    os.remove("temp.txt")

The @contextmanager decorator turns a generator into a context manager with minimal boilerplate.

9. Walk Directories with pathlib

Stop using os.walk() and os.path. pathlib is the modern way:

from pathlib import Path
py_files = list(Path("./src").rglob("*.py"))
recent = [f for f in Path("./logs").glob("*.log")
          if f.stat().st_mtime > yesterday]

Path objects are composable, readable, and work across platforms.

10. Debug with breakpoint() and Rich

Replace print() debugging with breakpoint() - it drops you into pdb automatically. But for richer output, use the rich library:

from rich import print
from rich.pretty import pprint
pprint(locals())

Senior developers know when to use a debugger versus print statements, and they choose tools that give them the most information with the least friction.

Wrapping Up

These tricks are not about showing off - they are about writing Python that communicates intent clearly, runs efficiently, and scales well. The best code is not the most clever. It is the code that is easiest to understand six months later when you are debugging at 2 AM.

Start with one or two of these in your next project. You will be surprised how quickly they become second nature.

评论
暂无评论