Tuesday, November 3, 2015

Understanding Pylint Warnings


I have been fixing pylint errors for a new codebase and trying to understand what the pylint errors, warnings, refactor-suggestions and so on mean. If you run pylint for your Python programs, you might’ve encountered one of the following warnings:

Dangerous default value [] as argument
Dangerous default value {} as argument

I found an article that gave a simple example to explain why. I read their explanation and tried their examples.

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


>>> def foo(x=None):
...        if x is None:
...            x = []
...        x.append(1)
...        print x
>>> foo()
[1]
>>> foo()
[1]
>>> foo()
[1]

I still couldn’t understand what it meant. I re-read the explanation. And then it hit me. There are 2 factors responsible for this behavior:

  1. Python has mutable and immutable data types. Dictionaries, lists, sets, etc are mutable. Strings, floats, integers, booleans etc are immutable.
  2. Default arguments are instantiated as objects during function definition time

If you invoke a function without any argument when its default argument value is immutable, the default value itself does not get updated within the function. It’s immutable. And the same immutable value is used as a default argument every time you invoke the function without any argument.

If you invoke a function without any argument when the default argument value is mutable, the default value does get updated within the function as it is mutable and can be changed and the same default object is used every time you invoke the function without any argument.



No comments:

Post a Comment