← Back

Common Pitfalls

Python
Published:


Global variables

A common problem when accessing variables from the global scope is that setting a variable makes it local, unless you use the global keyword.

Note: It’s better to avoid using global variables.

x = 10

def foo():
    x += 1
    print(x)

foo() # Error

Pass by reference with mutable variables

When you do this x = y, both x and y will point to the same object in memory. So, modifying x will also modify y.

To avoid this, you can use the copy package using deepcopy.

x = [1, 2, 3]
y = x

x.append(4)
print(y) # [1, 2, 3, 4]

Mutable function default arguments

When you use mutable objects as default arguments, they are shared across all calls to the function. E.g. lists, dicts, sets, class instance etc.

To avoid this, you can use None as the default value and then assign the default value inside the function.

def foo(x=[]):
    x.append(1)
    print(x)

foo() # [1]
foo() # [1, 1]

Modifying while iterating

While iterating through some mutable objects such as dict and sets, you can’t modify them. Will raise a RuntimeError.

To avoid this, you can create a copy of the object and iterate through it.

d = {1: 'a', 2: 'b'}

for key in d:
    if key == 1:
        del d[key] # RuntimeError

Late binding and closures

When you use a loop to create a list of functions, the loop variable is bound to the function at the time of execution, not at the time of creation.

To avoid this, you can use default arguments to bind the value at the time of creation.

def create_functions():
    return [lambda: i for i in range(3)]
    # List comprehension to create functions with i
    # Each lambda function is supposed to return the value of i from the range 0 to 2.
    # However, the value of i is not bound at the time of creation, but at the time of execution. Which is 2. each lambda captures the reference to i.

for func in create_functions():
    print(func())  # 2 2 2