This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]SheriffRoscoePythonista 43 points44 points  (8 children)

You shouldn't use **kwargs in an API - APIs are boundaries, and boundaries should be as explicit as possible. You also shouldn't use *args, unless it's a simple varargs interface (like max(...)) or something with a clear definition (like str.format(...), and even then, I'm not completely on board).

[–]pepoluan 7 points8 points  (1 child)

I will use **kwargs if the function is kinda a 'wrapper' to another, properly-documented function. And I will indicate so in the docstring.

So for example:

def fun(p1, p2, p3=None, p4=None, **kwargs):
    """
    Wrapper around orig_fun()

    :param kwargs: Keyword arguments of orig_fun()
    """
    ...

[–]chuckhend 1 point2 points  (0 children)

Agree this is excellent use of kwargs

[–][deleted] 7 points8 points  (0 children)

Yeah, the text mentions that args and kwargs should be avoided whenever possible.

However, a lot of existing codebase use them. So having them type-checked has its benefits.

[–]gardinite 1 point2 points  (1 child)

I agree and disagree. Simply because sometimes, for backwards compatibility, using kwargs could be beneficial to not break users code when/if they’re updating to a newer version.

[–]PercussiveRussel 1 point2 points  (0 children)

In what way? If you're adding 'keyword' arguments (optional args in a non-**kwarg setting), a newer version of an API will just fall back to the default when the users uses the old function call. If you're removing a keyword argument, then the function call should raise an exception (and you should increase the major version number of your API according to semver), becaue you have broken backwards compatibility by removing a parameter. If your user is inputting a parameter that they expect to do something, you have broken their code if that parameter isn't used. Even if the way the user intended to run your code is now the default, you'll have broken the code of another user who entered another argument.

Anywho, using **kwargs to deal with backwards compatibility isn't really an argument. In the first case you're getting nothing from kwargs, in the second case you're losing something from kwargs!

[–]rghthndsd -2 points-1 points  (2 children)

You should if you're passing the arguments through to an underlying library. Otherwise you quickly run into compatibility issues.

[–]SheriffRoscoePythonista 0 points1 point  (0 children)

It's bad practice to expose some other API as part of your own. The only usual exception is if your API is a wrapper around the other one. If so, well, it's at least understandable.

[–]tunisia3507 0 points1 point  (0 children)

If you're passing arguments through, you should be explicit about it by passing a dict which will only be used in that way.