Cara menggunakan python asterisk argument

The most widely known usage of the asterisk operator, also known as destructuring operator, in Python is its usage in functions.

Let’s say you have a function that can add values and returns the sum of these values:

What if you want to sum up an arbitrary number of values? You can add an asterisk in front of the argument’s name like so:

def add(*numbers):
    sum = 0
    for number in numbers:
        sum += number
    return sum

As you might have already noticed from the function’s body, we expect

my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
0 to be an iterable. Indeed, if you check the type,
my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
0 is a
my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
2. And, indeed, we can now call the function with an arbitrary number of arguments:

def add(number_1, number_2, number_3): return number_1 + number_2 + number_36 in the function call

We have seen so far that we can define a function so that it takes a list of parameters. But what if we have a function with a fixed set of arguments and we want to pass a list of values to it. Consider this function:

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3

This function takes exactly 3 parameters. Let’s assume we have a list with exactly three elements. Of course, we could call our function like this:

my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])

Luckily the destructuring operator (

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
6) works in both ways. We have already seen the usage in a function’s definition, but we can use it also to call a function:

my_list = [1, 2, 3]

add(*my_list)

def add(number_1, number_2, number_3): return number_1 + number_2 + number_38 in function definition

In the same way we can destructure lists with the asterisk (

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
6) operator, we can use the double-asterisk (
my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
7) operator to destructure dictionaries in Python functions.

Consider a function like this:

def change_user_details(username, email, phone, date_of_birth, street_address):
    user = get_user(username)
    user.email = email
    user.phone = phone
    ...

If we call it with keyword arguments (

my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
8), a function call might look like this:

change_user_details('bascodes', email='[email protected]', phone='...', ...)

In that case we could rewrite our function like this to accept an arbitrary number of keyword arguments that are then represented as a dictionary called

my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
8:

def change_user_details(username, **kwargs):
    user = get_user(username)
    user.email = kwargs['email']
    user.phone = kwargs['phone']
    ...

Of course, we can use the

my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
8 dictionary like any other dictionary in Python, so that the function might become a bit cleaner if we actually utilize the dictionary data structure like so:

def change_user_details(username, **kwargs):
    user = get_user(username)
    for attribute, value in kwargs.items():
        setattr(user, attribute, value)
    ...

my_list = [1, 2, 3] add(my_list[0], my_list[1], my_list[2])7 in the function call

Of course, the

my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
7 operator works for calling a function as well:

details = {
    'email': '[email protected]',
    ...
}
change_user_detail('bascodes', **details)

Restricting how functions are called

Keyword arguments only

One of the most surprising features of the asterisk in function definitions is that it can be used standalone, i.e. without a variable (parameter) name. That being said, this is a perfectly valid function definition in Python:

def my_function(*, keyword_arg_1):
    ...

But what does the standalone asterisk do in that case? The asterisk catches all (non-keyword) arguments in a list as we have seen above. There is no variable name in our case that would make the list. After the

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
6 we have a variable called
my_list = [1, 2, 3]

add(*my_list)
4. Since the
def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
6 has already matched all positional arguments, we’re left with
my_list = [1, 2, 3]

add(*my_list)
4, which must be used as a keyword argument.

Calling the above function with

my_list = [1, 2, 3]

add(*my_list)
7 will raise an error:

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
0

Positional arguments only

What if we want to force the users of our function to use positional arguments only – as opposed to keyword arguments only in the last example?

Well, there is a very Pythonic way. We interpret the

my_list = [1, 2, 3]

add(*my_list)
8 sign (the opposite of multiplication) to do the trick:

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
1

Surprisingly few Python developers know about this trick which has been introduced to Python 3.8 through PEP 570.

If you call the last function with

my_list = [1, 2, 3]

add(*my_list)
9, this will raise a TypeError:

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
2

Usage of def add(number_1, number_2, number_3): return number_1 + number_2 + number_36 and my_list = [1, 2, 3] add(my_list[0], my_list[1], my_list[2])7 in literals

The asterisk (

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
6) and double asterisk (
my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
7) operators do not only work for function definitions and calls, but they can be used to construct lists and dictionaries.

Constructing lists

Let’s say, we have two lists and want to merge them.

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
3

Of course, we could merge these lists with the

def change_user_details(username, email, phone, date_of_birth, street_address):
    user = get_user(username)
    user.email = email
    user.phone = phone
    ...
4 operator:

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
4

However, the

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
6 operator gives us a bit more flexibility. Let’s say, we want to include a scalar value in the middle, we could use:

Constructing dictionaries

Again, what is true for lists and the asterisk (

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
6) operator is true for dictionaries and the double-asterisk operator (
my_list = [1, 2, 3]

add(my_list[0], my_list[1], my_list[2])
7).

Destructuring lists

You might already know, that you can split elements of a list to multiple variables like so:

But did you know that you can use the asterisks (

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
6) to assign to variables when you have a list of arbitrary length?

Say, you want the first element and the last one of a list in a specific variable.

You can do this by using the asterisk like so:

def add(number_1, number_2, number_3):
    return number_1 + number_2 + number_3
5

In this example

def change_user_details(username, email, phone, date_of_birth, street_address):
    user = get_user(username)
    user.email = email
    user.phone = phone
    ...
9 now contains the first element, and
change_user_details('bascodes', email='[email protected]', phone='...', ...)
0 contains the last element of
change_user_details('bascodes', email='[email protected]', phone='...', ...)
1. What is in
change_user_details('bascodes', email='[email protected]', phone='...', ...)
2, however?

In

change_user_details('bascodes', email='[email protected]', phone='...', ...)
2, there is the entire list, excluding the first and last element, i.e.
change_user_details('bascodes', email='[email protected]', phone='...', ...)
4. Note that
change_user_details('bascodes', email='[email protected]', phone='...', ...)
2 is a list now.