Explain Codes LogoExplain Codes Logo

Hidden features of Python

python
generator-expressions
tuple-unpacking
dynamic-attributes
Alex KataevbyAlex Kataev·Nov 3, 2024
TLDR

Use the built-in variable __debug__ for optimization. It's a companion to the runtime execution of code profiling:

if __debug__: import cProfile cProfile.run('foo()') # Time to rock with your code block!

This technique takes advantage of Python's built-in profiling module. It's triggered when the script is not run in optimized mode (-O not set), providing a neat way to profile your code.

Building concise comparisons

Python supports chained comparisons offering you more natural and readable code, akin to mathematical notation!

if 1 < x < 10: # Python's subtle way of playing matchmaker! print(x)

This method is not only a relief for your eyes but also optimal for your machine as it only evaluates x once.

Simplifying regex with debug mode

Regex can be mind-boggling, but Python's got your back. re.DEBUG visualizes your pattern matching journey.

import re pattern = re.compile("your_complex_pattern", re.DEBUG)

Marry this with re.VERBOSE and voila, your regex can now host comments. How hospitable!

pattern = re.compile(""" [A-Z] # Uppercase alphabets, armoring the initial [0-9]+ # Numeric henchmen following the front \s # Rounding it up with a smooth space """, re.VERBOSE)

Generators: The memory conservers

Generators are your go-to when looping over large datasets. They're like those zero-waste products: you get what you need, as you need it.

# Memory-efficient as generators don't store the entire list in memory sum_of_squares = sum(n*n for n in range(1000)) # counteracting memory obesity, one square at a time!

When PEPs save your script

PEPs (Python Enhancement Proposals) are your recipe book for Python cuisine. They allow us to trace the lineage of Python: how its features are being enhanced and used.

# PEP 279 introduced `enumerate` for index, item in enumerate(['a', 'b', 'c']): print(index, item) # Look mom, I'm broadcasting on both frequencies: index and item!

The sentinel logic

The iter function helps to create sentinel loops - stops the loop when it encounters a marker/sentinel.

with open('text.txt') as f: for chunk in iter(lambda: f.read(10), ''): # Someone say 'chunk' reading? No more overeating! process(chunk)

Tracking indices in loops

enumerate, meet iteration indices. This beautifies your loops and drags Python closer to the natural style of counting.

for index, value in enumerate(my_list): # A smooth waltz between index and value print(f"{index}: {value}")

Tune up your loops with generator expressions for a musical performance of efficient cycling:

# Generator expression replacing nested loops coords = ((x, y) for x in range(5) for y in range(5)) # whisper 'cartesian product' three times in front of a mirror and this might just appear! for x, y in coords: print(x, y)

Packed and unpacked

Tuple unpacking works like slicing bread: different sizes for different needs.

head, *body, tail = range(10) # Pythonic dissection at its finest! # head = 0, body = [1, ..., 8], tail = 9

Dynamically working with attributes

Using getattr and setattr functions, you can dynamically tweak an object's attributes. It’s like playing dress-up with your data.

class MyClass: def __init__(self): self.attribute = "value" # Dynamically get attribute value = getattr(MyClass(), "attribute") # Python's magic trick to pull out attributes like rabbits from hats!

Loops with a little extra

Python outwits with its else in a loop structure. The else block executes when the loop ran peacefully without a break.

for item in container: if search(item): break else: # Executed after the loop but only if the loop wasn't forcefully exited using 'break'. not_found_action() # Act if item wasn't found, like hosting a microscopic hide-and-seek!