What does KWARGS in Python mean?

Asked

Viewed 7,137 times

5

I know that, in Python, we can define in a function something similar to what they call "named Parameters", ie, "named parameters".

def my_func(**kwargs):
    pass

my_func(nome="Stack Overflow", linguagem="Português")

I don’t know if my definition of "named parameters" is really the same goal as the argument kwargs function parameter (at least, it seems to me it is; and, if it is not, I would like to be corrected).

But, in practice, what would be the "KW" of this kwargs?

He is a dict or if it is another object?

2 answers

6

In fact, as can be seen in Soen’s reply, the question is more related to the syntax of an asterisk and two asterisks. When you use two asterisks, you will pass one dict, as you yourself quoted.

The kwargs It’s just a convention for KeywOrd Arguments (named parameters, as you assume), but the variable can be any name. If you want to pass an indefinite number of parameters, but without naming them, you would use only an asterisk, in the setting.

  • 1

    In this case, these arguments with an asterisk *args, would be like variadic functions of PHP 5.6?

  • @Wallacemaxters, I don’t know much about PHP to associate the two, but, by my understanding, it would be yes. At least when used in def. (:

4

As Felipe commented, the nomenclature of the parameter comes from keyword Arguments and, yes, it has a certain relationship with the named parameters. With the named parameters, you can set the order you want when calling a function or method. For example:

def fullname(firstname, lastname):
    return " ".join([firstname, lastname])

print(fullname("Anderson", "Woss"))  # Anderson Woss
print(fullname(lastname="Masters", firstname="Wallace"))  # Wallace Maxters

See working on Ideone | Repl.it

The use of **kwargs is given when you do not previously know the parameters that the function will receive. When using it, you are indicating that the Python interpreter must collect all named parameters not provided in the list of arguments, but that were passed when invoking the function/method, creating a dictionary called kwargs.

def fullname(firstname, **kwargs):
    return " ".join([firstname] + list(kwargs.values()))

print(fullname(firstname="Anderson"))  # Anderson
print(fullname(firstname="Anderson", middlename="Carlos", lastname="Woss"))  # Anderson Carlos Woss

See working on Ideone | Repl.it

It is important to note that even kwargs representing a dictionary, the order of the values is maintained the same in which it is indicated in the function parameters, thanks to the PEP 468 - Preserving the order of **kwargs in a Function. That is, the behavior of kwargs resembles more of a collections.OrderedDict that a common dictionary.

But when I don’t know the parameters the function will receive?

One of the main uses of *args and **kwargs is in the definition of decorators. By definition, a decorator will always return a function that will represent the decorated function in the context in which it was defined. That is, when I call a decorated function, what will be executed in the first instance is the function that the decorator returned, not the function itself. Since, when defining a decorator, we do not know what are the parameters that the function to be decorated defines, we use the parameters *args and **kwargs. Take an example:

def decorator(function):
    def wrapper(*args, **kwargs):
        print("Antes de chamar a função", function.__name__)
        function(*args, **kwargs)
        print("Depois de chamar a função", function.__name__)
    return wrapper

@decorator
def foo(name):
    print(name)

@decorator
def bar(number):
    print(2*number)

foo("Anderson")
bar(2)

See working on Ideone | Repl.it

The result will be:

Antes de chamar a função foo
Anderson
Depois de chamar a função foo
Antes de chamar a função bar
4
Depois de chamar a função bar

Note that when defining the function decorator decorator, we do not know what parameters the decorated function will receive, but when using the *args and **kwargs ensure that all parameters are properly passed to the function.

Remember that using the parameters *args and **kwargs does not necessarily exclude the use of explicit parameters. That is, it is possible to use in a function both positional arguments, named and yet the *args and **kwargs. For example:

def foo(arg_1, arg_2, *args, arg_3=3, **kwargs):
    ...

But it is important to note that the order, in this case, should always be:

  1. Positional arguments;
  2. *args;
  3. Named arguments;
  4. **kwargs;

This is because Python requires that positional parameters always come before the nominees.


Responding to commenting, the equivalent of doing function (...$args) PHP 5.6+ in Python is *args, not the **kwargs, once while doing ...$args you will get a array sequential with the values passed as parameters, as well as the *args will be a list of values passed by unnamed parameters. Since PHP has no named parameters, there is no equivalent to **kwargs python.


Additional readings

Related

Browser other questions tagged

You are not signed in. Login or sign up in order to post.