Contrary to most reactions, I find it natural and desirable to accept None
as an alternative to omit an optional parameter in a wide variety of APIs. Not because I like to read or write log(2.3, None)
but because I like to be able to define a simple wrapper, e.g.
def my_log(x, base=None):
# <extra stuff here>
return math.log(x, base)
This allows both my_log(x)
and my_log(x, base)
to be called, and my_log()
doesn’t have to hard-code knowledge about the default base. While it is possible to write a wrapper that accepts an optional extra argument and passes that on only when present, it is uglier and harder to read, e.g.
def my_log(x, *args):
assert len(args) in (0, 1))
# <extra stuff here>
return math.log(x, *args)
This is slower too (even if you take out the assert
) because handling *args
takes a slower path in the interpreter. And why should you have to do it this way?
(EDIT: The version with *args
also makes it more awkward to access base
in the wrapper in case the “extra stuff” wants to intercept a certain base.)