Python is interpreted as a high-level programming language with its easy-to-learn syntax and dynamic semantics. It is widely used for rapid application development due to its large support of modules and packages and code reuse along with program modularity.

Python’s simple syntax may often mislead developers - especially if they are new to the language. This blog covers some of the top mistakes that even an advanced Python developer can make.


1. Modifying a list while iterating

Deleting an element from an array or list when iterating over it, is a well-known Python problem to most of the developers.

>>> foo = lambda x : bool(x % 2)
>>> nums = [n for n in range(10)]
>>> for i in range(len(nums)):
...     if foo(nums[i]):
...         del nums[i]  # Deleting item from a list while iterating over it

 

This results in an IndexError getting raised. List comprehensions are particularly useful for avoiding this specific problem.


2. Weak error handling

Usage of exception handling always comes in handy. But, what if statements are not put inside a try-catch block when an unforeseen error occurs but was one which could have been bypassed or maybe just logged for later reference? The absence of exception block in such a scenario will abort the execution without any informative message from the application.

Also, In cases where multiple exceptions are to be captured, if we write the following code:

try:
    # statement
except ValueError, IndexError:
    pass

 

The problem here is that the except statement does not take a list of exceptions specified in this manner. Instead, it has to write as:

try:
    # statement
except (ValueError, IndexError) as e:  
    pass

 

The proper way to catch multiple exceptions is to specify the first parameter as a tuple containing all exceptions to be caught. Also, for maximum portability, use the “as” keyword, since that syntax is supported by both Python 2 and Python 3.


3. Circular module dependencies

Importing a module recursively may cause a circular dependency in your program. Suppose you have two files, abc.py and xyz.py, each of which imports the other, as follows:

In abc.py:

import b
def f():
    return b.x
print f()

 

And in xyz.py:

import a
x = 1
def g():
    print a.f()

 

You will face some problems depending on the point at which each module is attempting to access functions or variables defined in the other.


4. Inconsistent indenting

In indentation of a particular single block, the spaces and tabs should never be mixed unless the exact reaction between the system and codes are studied thoroughly. Otherwise whatever is seen in the editor may not be the thing that is seen by the Python when the tabs are being counted as a number of spaces. So the best thing to do here is to use all spaces or all tabs for every block; the number to be used is entirely up to you.


5. Ignorance of Python scope rules

Python uses a different approach for scoping variables than other programming languages. For example, it allows accessing the variables declared inside loops or if statements from outside. It could be a bit confusing for someone coming from a C/C++ background.

Python scope resolution is known as the LEGB rule, which is shorthand for Local, Enclosing, Global, Built-in. You can have a concise idea of LEGB rule here

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

 

The above program results in “UnboundLocalError: local variable 'x' referenced before assignment” which will occur because, when you make an assignment to a variable in a scope, that variable is automatically considered by Python to be local to that scope and shadows any similarly named variable in any outer scope.


6. Misusing The __init__ method

The __init__ methods are used as constructors in Python. It automatically gets called when Python allocates memory to a new class object. The purpose of this method is to set the values of instance members for the class object.

Trying to explicitly return a value from the __init__ method implies that you want to deviate from its actual purpose.

A solution for this is to add a new property and move the desired logic to a different instance method.

class 

Student:
    def __init__(self, name, total_marks):
        self.name = name
        self.total_marks = total_marks
        self._percent = total_marks/12
 
    @property
    # Relocated the logic for returning the percent to a new 

method.
    def getPercent(self):
        return self._percent
        
stud = Student("Brian Tyler", 1035)
print(stud.getPercent)


7. Name clashing with Python Standard Library modules

Python is abundant with its large number of library modules which comes out of the box. But problems can occur if you run into a name clash between the name of one of your modules and a module with the same name in the standard library that ships with Python.

This will result in importing another library which in turn tries to import the Python Standard Library version of a module but, since you have a module with the same name, the other package mistakenly imports your version instead of the one within the Python Standard Library.

Care should, therefore, be taken to avoid using the same names as that of standard Python libraries.


Conclusion

Python is indeed a powerful language with many mechanisms that can greatly improve productivity. But having a limited understanding of its capabilities can sometimes be a hindrance. Familiarizing with the concepts of Python in a much greater depth will surely help you overcome these common mistakes, and build a stable and scalable final product.

Subscribe to our newsletter. Get updates on awesome happenings in the technology world!
Newsletter subscription successfull! Something went wrong! Email is already registered!

TAGS