Being aware of these 5 Python Pitfalls can save you hours of debugging effort.
Credits go to the wtfpython repository!
1. String concatenation without "+"
Two strings are implicitly concatenated if they are written after each other, even without using the "+" operator. This can be relevant, e.g., if we have a list of strings and forget one comma.
Notice the missing comma in the list:
my_list = ["one", "two" "three", "four", "five"] >>> len(my_list) 4 >>> my_list ["one", "twothree", "four", "five"]
Instead of raising a
SyntaxError, these strings are simply combined and we get unexpected results!
Implicit string concatenation:
a = "hello" "world" >>> a helloworld
2. Conditional expression and multiple assignments
In Python we can assign multiple variables in one line. Also, we can use a conditional expression instead of the longer if-else statement.
If both features are combined, we have to be really careful!
condition = False x, y = (0, 1) if condition else None, None >>> x, y (None, None)
This is what we expected, but what happened if the condition is True?
condition = True x, y = (0, 1) if condition else None, None >>> x, y ((0, 1), None)
Now we get three values, what is happening???
Explanation: We tried to use parenthesis to improve the readability, but now we messed up the evaluation order! Now x will be (0, 1) if the condition is True, and None otherwise. And y is always None.
Either use consistent parenthesis for both cases:
condition = True x, y = (0, 1) if condition else (None, None) >>> x, y (0, 1)
Or in this case I prefer the normal if-else statement, which is less error-prone:
if condition: x, y = 0, 1 else: x, y = None, None
3. Tuple creation with one element
Let's create tuples with different numbers of items, and inspect the items. As you know, tuples are created by using parenthesis
t = ('one', 'two') for i in t: print(i) # Output: one two
This is what we expected for two elements.
Now create an empty tuple:
t = () for i in t: print(i) # Output:
No output, also what we expected.
Now create a tuple with one element:
t = ("one") # This is a string, not a tuple!!! for i in t: print(i) # Output: o n e
We print three items with one character each! What is happening???
Explanation: If we create a tuple with one element with parenthesis, the used syntax does not create a tuple but a string object!
A comma inside the parenthesis MUST be used to create a tuple with one element:
t = ("one",) for i in t: print(i) # Output: one
One could have the idea to use the explicit tuple constructor by using the
tuple() function. This will indeed create a tuple object, but when passing a string to this function, it creates a tuple with one character for each item:
t = tuple("one") # ('o', 'n', 'e')
I have a detailed tutorial about tuples here.
assert statement with parenthesis
The assert statement in Python is a convenient way to insert debugging assertions into a program:
If the condition is True, nothing happens, but if the condition is False, an AssertionError is raised (only in debug mode). This can be used to catch bugs when when we always expect a certain condition to be True.
The assert statement can take an optional Error message, separated by a comma:
Why is no AssertionError raised when the two variables are obviously not equal?
Explanation: The assert statement should NOT be used with parenthesis! Otherwise the whole statement is evaluated as one tuple with a Boolean and a string, and a non-empty tuple is always True.
Syntax according to the official docs is without parenthesis:
assert expression ["," errormsg]
5. In-place update methods of Lists/Dictionaries
This might be obvious, but sometimes we still forget it and then get unexpected None values.
Certain methods for Lists like
sort() modify the List in-place and return None! So when we assign the result of this operation back to the original variable, the object is None:
my_list = [1, 3, 2] my_list = my_list.append(4) # or my_list = my_list.sort() >>> my_list None
Simply apply these methods without reassigning it to the variable:
my_list = [1, 3, 2] my_list.append(4) my_list.sort() >>> my_list [1, 2, 3, 4]
Same holds true for Dictionaries and the