The Most Common Python Programming Mistakes, And How To Avoid Them

Python is an incredibly popular, and at the same time, high-level programming language, mostly due to its relative simplicity in comparison to some other notable languages, including Java and C++. It is particularly great when looking to build data structures, but it is also compatible with almost all platforms: another reason why it is a crowd pleaser. That said, there are still a number of common traps that developers can fall into when programming in Python, mainly brought about by wrongly assuming its simplicity does not include subtlety.

The incorrect usage of expressions, especially as defaults when making function arguments

One of the most attractive possibilities of Python is that the language allows function arguments to be specified as optional, just by creating a default value for this function argument. But simply speaking, it is wrong to assume that this will happen every single time a function is requested because the value will still need to be prescribed.

This error comes about in situations where the default expression that you are looking to use is mutable. The issue here is that evaluation was only played out once when the definition of the function took place. This is the major oversight developers can make.

>>> def foo(bar=None):
...    if bar is None:          # or if not bar:
...        bar = []
...    bar.append("baz")
...    return bar
...
>>> foo()
["baz"]
>>> foo()
["baz"]
>>> foo()
["baz"]

Not using class variables as they should be used

Class variables are of course immensely useful, but their usage has to be followed closely. The problem may arise because a class attribute in Python is attributable to a class rather than an attribute pertaining to the instance of a class. It is then important to follow the understanding of the way that the subsequent class variables actually follow a Method Resolution Order, because of the issue of multiple inheritances. In short, the Python system will handle these variables as dictionaries.

Creating an exception block but creating the wrong specifying parameters

Exception blocks will always be necessary, but be sure that you do not incorrectly prescribe the parameters. When creating multiple exceptions, the first exception must be specified as a tuple, which is a standard sequence data type.

>>> try:
...     l = ["a", "b"]
...     int(l[2])
... except ValueError, IndexError:  # To catch both exceptions, right?
...     pass
...
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
IndexError: list index out of range

A failure to grasp the scoping rules for Python

This is a common error, mainly because many developers come at Python with a background in another programming language, such as C++, and then there is a failure to appreciate that the scoping rules are in fact a little different. What would be highly recommended is to get a handle on LEGB, which is what Python uses when searching for names. In short, it is:

L – Local
E – Enable
G – Global
B – Built-ins

With an appreciation of this rule, the approach to scoping variables can be differentiated from the approach in other languages, avoiding a crossover.

>>> x = 10
>>> def foo():
...     x += 1
...     print x
...
>>> foo()

Using knowledge of Java to inspire get/set functions

If you are coming from a Java background, of course, you will be familiar with the best practice method of defining the ‘getter’ and ‘setter’ functions when wanting to access the members of a class. But this will bring very little benefit in Python, for a ream of extra code.

It’s normal to be influenced by what you are used to, but it would be to your advantage here to remember that it’s fine in Python to use direct access or manipulation of a class member, and you can also utilize property decorators to get the functionality you are looking for.

Iterating over a list, but then attempting to modify it at the same time

Most developers will be aware of this Python-unique issue of deletion of something from a list at the same time it is being iterated over. That is not to say that mistakes can and will still be made.

Often the solution is to just keep it simple because the rule of thumb would be that simple code would be less likely to suffer from this issue. List comprehensions are also an invaluable way of avoiding this particular pitfall.

>>> odd = lambda x : bool(x % 2)
>>> numbers = [n for n in range(10)]
>>> for i in range(len(numbers)):
...     if odd(numbers[i]):
...         del numbers[i]  # BAD: Deleting item from a list while iterating over it
...
Traceback (most recent call last):
          File "<stdin>", line 2, in <module>
IndexError: list index out of range

Not understanding the way in which variables are bound in closures with Python

The cause of this common issue is relatively simple to explain: it is because of the late binding manner of Python. It all comes down to the timing of the calling of the inner function and the variable values utilized in the closures.

Fortunately, the solution is pretty straightforward too, in that it’s really a bit of a hack: just generate anonymous functions. All you are really doing is exploiting the default argument.

Conclusion

Like mistakes made in so many other fields of endeavor, such as speaking a second language, programming issues in Python will mainly arise from a reliance upon the systems and processes used in your background language – that is your mother tongue is we were to continue the spoken language metaphor. By appreciating these subtleties in the way the Python language operates, future errors can be avoided.

Related learning

S.O.L.I.D the First 5 Principles of Object Oriented Design with JavaScript
The global tech industry is moving to .tech domains. What about you?
Node.js MongoDB Tutorial

Pankaj Kumar
Pankaj Kumar
Articles: 208