There isn’t any reason not to use keyword arguments apart from the clarity and readability of the code. The choice of whether to use keywords should be based on whether the keyword adds additional useful information when reading the code or not.
I follow the following general rule:
- If it is hard to infer the function (name) of the argument from the function name – pass it by keyword (e.g. I wouldn’t want to have
text.splitlines(True)in my code). - If it is hard to infer the order of the arguments, for example if you have too many arguments, or when you have independent optional arguments – pass it by keyword (e.g.
funkyplot(x, y, None, None, None, None, None, None, 'red')doesn’t look particularly nice). - Never pass the first few arguments by keyword if the purpose of the argument is obvious. You see,
sin(2*pi)is better thansin(value=2*pi), the same is true forplot(x, y, z).
In most cases, stable mandatory arguments would be positional, and optional arguments would be keyword.
There’s also a possible difference in performance, because in every implementation the keyword arguments would be slightly slower, but considering this would be generally a premature optimisation and the results from it wouldn’t be significant, I don’t think it’s crucial for the decision.
UPDATE: Non-stylistical concerns
Keyword arguments can do everything that positional arguments can, and if you’re defining a new API there are no technical disadvantages apart from possible performance issues. However, you might have little issues if you’re combining your code with existing elements.
Consider the following:
- If you make your function take keyword arguments, that becomes part of your interface.
You can’t replace your function with another that has a similar signature but a different keyword for the same argument. - You might want to use a decorator or another utility on your function that assumes that your function takes a positional argument. Unbound methods are an example of such utility because they always pass the first argument as positional after reading it as positional, so
cls.method(self=cls_instance)doesn’t work even if there is an argumentselfin the definition.
None of these would be a real issue if you design your API well and document the use of keyword arguments, especially if you’re not designing something that should be interchangeable with something that already exists.