Using default arguments of the form x={} usually does not accomplish the intended purpose in Python, since default arguments are bound when a function is defined, not called.
The convention seems to be to set mutable objects as default arguments with x=None and then check x is None to assign the proper default when the function is called.
So if I would like to cast x to a dictionary that is by default empty, I would use something like the following:
def f(x=None):
x = dict(x) if x is not None else {}
However, since dict can take any iterable, I could also write this more succinct version:
def f(x=()):
x = dict(x)
Which of these is the “right” approach?
The idiomatic style is to not cast to
dict; that way someone could use any object that implements the correct mapping methods.So, the most pythonic method is to use:
and then just use mapping methods.
So, you generally should not cast arguments to a dict. You state your API accepts a mapping object instead, and expect callers to do the casting.
The only reason to accept both a
dictand an iterable is when you want to support ordered key-value pairs where duplicate keys are allowed, such as for theurllib.urlencodefunction. In such a case adictcannot retain that information, and that method does not cast the iterable to a dict, but rather uses the dict as an iterable.