Require Keyword Arguments |
July 13th, 2014 |
python, tech |
To avoid errors in calling a python function you might want to ensure
it's only ever called with keyword arguments. Say you have:
def score(actual, predicted): ...and you're worried people accidentally call it with the arguments reversed. After all, nothing looks surprising with:
score(model.predict(data), isRepaid)We can have a culture where everyone writes in the keyword arguments, as:
score(actual=isRepaid, predicted=model.predict(data))This mostly solves the problem, but could we have Python check this for us? Yes! PEP 3102 added this to Python 3+:
def score(*, actual, predicted): ..But what about the Python 2 series? You could rebuild Python with this patch applied, or you could use a decorator that verifies there are no positional arguments and then calls the original function:
def poscheck(f): def checked_f(*args, **kwargs): if args: raise PositionalArgumentsError(f) f(**kwargs) return checked_f @poscheck def score(actual, predicted): ...This is pretty good, but what about a case like this:
# Split s on newlines ('\n'), returning a list. These newlines # are not normally retained, but if the optional keepends argument # is True then they're kept. def splitlines(s, keepends=False): ...If someone calls
splitlines
as
splitlines(s, True)
that's going to be pretty
confusing to a reader. You'd like to make sure writers always make it
clear what the boolean is about, so you have a house style where you
write splitlines(s, keepends=True)
. If you used
poscheck
, though, that would require
splitlines(s=s, keepends=True)
which is too
verbose. So, use poscheck_except
instead:
@poscheck_except(1) def splitlines(s, keepends=False): ...This will require that after the first positional argument all other arguments are given with keywords, if present.
The code is poscheck
on
github.
Comment via: google plus, facebook