Python Mistakes
Python is an incredibly easy language to learn and doesn’t force you to use specific conventions. It’s also easy to fall into some pitfalls that make you stand out as a beginner. To avoid looking like a complete beginner, check out the tips below and how to fix them.
1. Not Using enumerate()
Python makes iterating over things like lists super easy. Take a look at the example below:
vals = ['Python', 'is', 'fun!']
for val in vals:
print(val)
# Returns:
# Python
# is
# fun!
But what happens if you need to reference the index of each item? You may have come across or even written code like the one shown below:
vals = ['Python', 'is', 'fun!']
for i in range(len(vals)):
print(i, vals[i])
# Returns:
# 0 Python
# 1 is
# 2 fun!
While this works, it’s not exactly elegant! It also doesn’t immediately make it clear what your code is doing.
This is where the `enumerate()` function comes to the rescue! Let’s take a look at how much easier it makes this process:
vals = ['Python', 'is', 'fun!']
for idx, val in enumerate(vals):
print(idx, val)
# Returns:
# 0 Python
# 1 is
# 2 fun!
Isn’t that so much better?
As a pro tip, you can even change the starting value. Say you wanted to label items starting at 1, instead. Then you can simply write:
vals = ['Python', 'is', 'fun!']
for idx, val in enumerate(vals, start=1):
print(idx, val)
# Returns:
# 1 Python
# 2 is
# 3 fun!
Alright, let’s dive into the next beginner habit!
2. Not Using the Ternary Operator
When you’re an if-else statement to assign a value, you’re using a lot of lines of code for a simple action. Take a look at the scenario below:
amount = 100
if amount > 50:
raise_amount = 20
else:
raise_amount = 10
print(raise_amount)
# Returns:
# 20
In the example above, we’re creating an if-else statement that checks if the amount someone sold is over 50. If it is, then they get a raise of 20. Otherwise, they get a raise of 10.
While our code is clean, it’s not exactly concise. We can simplify this dramatically by using the ternary assignment:
amount = 100
raise_amount = 20 if amount > 50 else 10
print(raise_amount)
# Returns:
# 20
This works best for really simple assignments. While you _can_ get more complex, don’t sacrifice readability over conciseness!
3. Not Using Comprehensions
Python comprehensions make short work of creating lists, dictionaries, and even generators. They provide an elegant and readable way to easily create data structures.
Let’s take a look at an example of how you would use a for-loop to write create a list of squared numbers:
squares = []
for i in range(1, 6):
squares.append(i ** 2)
print(squares)
# Returns:
# [1, 4, 9, 16, 25]
Now let’s compare this to a list comprehension:
squares = [i ** 2 for i in range(1, 6)]
print(squares)
# Returns:
# [1, 4, 9, 16, 25]
We can see how much simpler and explicit using the list comprehension is! Not only is the code more concise, but it’s also much easier to read.
It’s just as easy to create a dictionary comprehension. Let’s compare the two approaches again by creating a dictionary where the key is the original number and the value is its square:
squares = {}
for i in range(1, 6):
squares[i] = i ** 2
print(squares)
# Returns:
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
Now let’s take a look how we can simplify this with a dictionary comprehension!
squares = {i: i**2 for i in range(1, 6)}
print(squares)
# Returns:
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
Now, it’s also easy to go overboard and use comprehensions for everything. So I’ll throw in a bonus tip here: don’t use them for everything unless it makes sense to!
3b. Going Overboard with Comprehensions
Python comprehensions are powerful — really powerful. You can build in complex if-else statements and even nest them in one another.
Let’s take a look at how we can incorporate if-else statements:
even_odd_numbers = [
"Even" if num % 2 == 0 else "Odd"
for num in range(10)
]
print(even_odd_numbers)
# Returns:
# ['Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd']
In the example above, we use the ternary operator to return a value while continuing to iterate. Now, this example is pretty simple — but let’s take a look at a more complex one:
result = [x * 2 if x % 2 == 0 else x * 3 for x in range(10) if x != 5]
Oof! Well, that’s no fun at all to read. And that brings to my main point — don’t write comprehensions if they’re less clear than using a for loop.
Let’s convert this comprehension to a loop to see how much easier it is to read:
result = []
for x in range(10):
if x != 5:
if x % 2 == 0:
result.append(x * 2)
else:
result.append(x * 3)
We can see that while we’re using more lines to write this code, it’s so much more readable!
4. Not Using itertools
Python’s itertools is a hidden gem built right into Python. While on the surface, many of its functions seem simple, they provide elegant and powerful ways to iterate over different objects.
Preventing Nested Looping
Say you have two lists and you want to iterate over all possible combinations. You could write a nested for loop like the one shown below:
colors = ['Red', 'Green']
sizes = ['S', 'M', 'L']
for color in colors:
for size in sizes:
print(color, size)
# Returns:
# Red S
# Red M
# Red L
# Green S
# Green M
# Green L
Similar to everything else we’ve walked through in this article, this approach works, but it’s not exactly elegant.
Thankfully, itertools comes with the product() function, which creates a Cartesian product of all the items. This means we can unpack the values directly in a single for-loop, as shown below:
from itertools import product
colors = ['Red', 'Green']
sizes = ['S', 'M', 'L']
for color, size in product(colors, sizes):
print(color, size)
# Returns:
# Red S
# Red M
# Red L
# Green S
# Green M
# Green L
We can see how much simpler this approach is!
Looping Over Lists Pairwise
In some cases, you’ll need to iterate over a list in pairs, meaning you need to access an item and its neighbor.
To do this, you could write the following code:
vals = [1, 2, 3, 4]
for i in range(len(vals) - 1):
print((vals[i], vals[i+1]))
# Returns:
# (1, 2)
# (2, 3)
# (3, 4)
This approach works well, but it’s not easily readable, nor is it very explicit in what it does.
This is where the `pairwise()` function, introduced with Python 3.10, comes in handy! Let’s take a look at how we can simplify our code:
from itertools import pairwise
vals = [1, 2, 3, 4]
for pair in pairwise(vals):
print(pair)
# Returns:
# (1, 2)
# (2, 3)
# (3, 4)
This is a much more explicit version of the code we’d written before, allowing us to immediately understand the code’s purpose.
The itertools library gives you many useful functions for iterating over objects. Knowing when to apply these functions really take your skills to another level.
Mastering Python is more than just remembering syntax — it’s about embracing elegance and knowing when to balance conciseness with readability.
Remeber the Zen of Python:
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
The tips above should really help you embrace these first lines of the Zen of Python!
Do you have any other tips you love? Feel free to share them in the comments below