Putting a * operator before a tuple, list or generator, in a function call will unpack it and pass its elements as separate positional arguments to the called function.
def print_coordinate(x, y):
print(x, y)
# tuple
coordinate = (1, 2)
print(*coordinate)
# list
coordinate = [3, 4]
print(*coordinate)
# generator
coordinate = (x for x in range(5, 7))
print(*coordinate)
# outputs:
1 2
3 4
5 6
Similarly, the ** operator will unpack keyword arguments from dictionaries and pass them to the called function.
def print_coordinate(x, y):
print(x, y)
coordinate = {'x': 7, 'y': 8}
print_coordinate(**coordinate)
# outputs:
7 8
Another example:
def print_team(name, captain, rank):
print(f'{name}, captained by {captain}, is ranked number {rank}')
# tuple
australia = ('Australia', 'Ponting', 1)
print_team(*australia)
# list
australia = ['Australia', 'Ponting', 2]
print_team(*australia)
# generator
australia = (x for x in ['Australia', 'Ponting', 3])
print_team(*australia)
# dictionary
australia = {'name': 'Australia', 'captain': 'Ponting', 'rank': 4}
print_team(**australia)
# outputs:
Australia, captained by Ponting, is ranked number 1
Australia, captained by Ponting, is ranked number 2
Australia, captained by Ponting, is ranked number 3
Australia, captained by Ponting, is ranked number 4
You may need to unpack specific values from an iterable, again the * operator is very useful. Here we grab the first and last name, and assign any other names to other – from the list middle:
def greet_new_member(fullname):
first, *middle, last = fullname.split(' ')
other = " ".join(middle)
print(f'Member: {last}, {first} ({other})')
print(f'Welcome {first}')
greet_new_member("Rainen Anthony Yi Hao Harper")
# outputs:
Member: Harper, Rainen (Anthony Yi Hao)
Welcome Rainen