|July 13th, 2014|
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(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(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
- Contra Dance Unplugged
- Transit Service Quality Map
- OK to Have Kids?
- Simplest Interesting Game
- Tracking Down a Statistic: Does Fairtrade Work?