Explain Codes LogoExplain Codes Logo

Accessing the index in 'for' loops

python
enumerate
pythonic
iterators
Nikita BarsukovbyNikita BarsukovΒ·Sep 16, 2024
⚑TLDR

Get indexes circular during iteration with magic balls: enumerate(). In Pythonia, we don't count sheep, we enumerate(sequence):

for idx, val in enumerate(sequence): print(idx, val) # idx loves val, idyllic Pythonic love

Our loop through sequence yields the index idx and value val for each element. Our mighty enumerate() starts counting from 0 (because 0-based index is cool 😎) by default. But he's flexible. To change, you can add a second parameter, like enumerate(sequence, 1) for 1-based index.

Turning boring iteration into a fun carnival ride with enumerate()

With enumerate(), your Python loops are clearer, more Pythonic, and rid the dreaded need to manage an external counter. Kiss goodbye to for i in range(len(xs)) and those pesky little variables for index tracking. Talk about non-idiomatic and clunky!

# Let's be honest. This old school way is as exciting as watching grass grow. 😴 for i in range(len(sequence)): print(i, sequence[i]) # So instead, put on your party hat and do this. πŸ₯³ for idx, val in enumerate(sequence): print(idx, val) # idx and val, sitting in a tree, K-I-S-S-I-N-G

Tuple unpacking is like Python's magician pulling a rabbit πŸ‡ out of a hat 🎩. It works wonders with enumerate():

index, item = next(enumerate(sequence)) # index and item, the dynamic duo

And for human-friendly counting (because we're humans, not computers), we start from one:

for idx, val in enumerate(sequence, start=1): print(f"Item {idx}: {val}") # idx Β‘Uno! Dos! Tres with val

Conquering kingdoms beyond loops with enumerate()

Slaying the two-headed beast

What if you're battling the mighty two lists monster? No need to fear! enumerate() and zip() are our armored knights, ready to tackle them with grace:

for idx, (item1, item2) in enumerate(zip(sequence1, sequence2)): print(f'Index {idx}: Item1 = {item1}, Item2 = {item2}') # idx, item1, item2: The Three Musketeers of Python. All for one, one for all!

Nimble acrobats in list comprehensions

In the circus of list comprehensions, enumerate() is our agile acrobat, performing mind-blowing stunts:

indexed_items = [(idx, val) for idx, val in enumerate(sequence)] # idx and val, putting on an astonishing performance!

The unseen performers – other iterables

enumerate() isn't picky. It can sweep everyone off their feet, handling strings, tuples, and more, like the Argentinian tango dancer it is!

Threading the needle with iter() and next()

In the rare ruby-encrusted cases where enumerate() isn't the crown jewel, iter() and next() are your diamond cutters, finding their place:

iterator = iter(sequence) while True: try: item = next(iterator) # Iterator, my dear Watson except StopIteration: break

The hidden treasure of manual counters and custom enumeration

Your trusty old compass: manual counters

For the times where the map doesn't match the terrain, a manual counter guides your nested loops or when you need to skip elements:

counter = 0 for item in sequence: if some_condition(item): # some_condition(), playing hard to get print(f"Index {counter}: {item}") counter += 1 # Easy does it, counter, the night is still young!

Transmuting lead into gold with a custom generator

Create your own philosopher's stone by forming a custom generator with yield:

def custom_enumerate(iterable, start=0): # iterable and start, partners in crime index = start for item in iterable: yield index, item # Generously yielding index and item like philanthropists of code index += 1

The hidden underground city: PEP 279

Want to dive deeper into the catacombs of enumerate()? Take a torch πŸ”¦ and explore PEP 279, a treasure trove of wisdom.