Ettearvamatu hulk argumente (*args, **kwargs)

Tihti tuleb ette olukordi, kus soovime funktsioonile anda sisse erineva koguse argumente või nimelisi argumente (keyword arguments). Seega võib kohata funktsioonide definitsioonides järgnevat kirjapilti: def bacon(*args, **kwargs).

Vaatame kõigepealt *args (arguments) kasutust. Muutuja nimi ei pea tingimata olema args vaid võib vabalt olla ka midagi muud, args on lihtsalt kujunenud konventsiooniks. Tärni kasutus muutuja ees lubab saata funktsioonile määramata koguse (nimetuid) argumente.

Soovides luua funktsiooni, mis summeeriks sissetulevad arvud sõltumata kogusest, peaksime tegema funktsiooni kahe parameetriga, kolme parameetriga jne, aga * muutuja ees võimaldab seda mugavalt teha.

# no pec def sum_all(*numbers: int) -> int: total = 0 # numbers is a tuple containing all the positional arguments for numbers in numbers: total += numbers return total print(sum_all(45, 32, 89, 78)) # Prints 244 print(sum_all(2)) # Prints 2

Vaatame veel olukordi, kus lisaks positsioonilistele parameetritele on esimesel funktsioonil ka formaalne parameeter:

# no pec def multiply(initial: int, *args: int) -> int: result = initial for arg in args: result *= arg return result print(multiply(1, 2, 5)) # --> 10 print(multiply(0, 2)) # --> 0 # We can also use the same syntax to unpack numbers = (1, 2, 3) print(multiply(1, *numbers)) # --> 6
# no pec def print_all_args(*args): print(args) print_all_args(1) # --> (1,) print_all_args(1, 2) # --> (1, 2) print_all_args(5, 'cookie', [13, 14]) # --> (5, 'cookie', [13, 14])
# no pec def join_numbers(*numbers: int, separator=',') -> str: """Join numbers into a string using given separator or default comma.""" return separator.join(map(str, numbers)) print(join_numbers(1, 2, 3)) # --> 1,2,3 print(join_numbers(21, 10, 2018, separator='.')) # --> 21.10.2018 values = [3, 3] # With a variable print(join_numbers(*values, separator='|')) # --> 3|3 # Without a variable print(join_numbers(*(0, 2, 3))) # --> 0,2,3

**kwargs (keyword arguments) toimib analoogiliselt ja lubab määramata koguses nimelisi argumente. Samuti pole oluline muutuja nimi, aga muutuja ees peab olema **. Kui *args puhul oli parameetrina tegemist ennikuga (Ennik (tuple)), siis kwargs-i puhul luuakse sõnastik (Sõnastik (dict)). Vaatame näiteid:

# no pec def print_kwargs(**kwargs): print(kwargs) # A dictionary will be made (not ordered before Python 3.6) print_kwargs(name='Guido', age=62, is_cool=True) # Prints {'name': 'Guido', 'age': 62, 'is_cool': True}
# no pec def print_key_value_pairs(**kwargs): for key, value in kwargs.items(): print(f'Key: {key}, Value: {value}') print_key_value_pairs(attack=20, defense=12.5, hasEvolved=False) # Key: attack, Value: 20 # Key: defense, Value: 12.5 # Key: hasEvolved, Value: False # The same as above, but pass a dictionary player_data = {'attack': 20, 'defense': 12.5, 'hasEvolved': False} print_key_value_pairs(**player_data) # Key: attack, Value: 20 # Key: defense, Value: 12.5 # Key: hasEvolved, Value: False
# no pec def foo(arg, *args, kwarg_1=True, **kwargs): print(arg, args, kwarg_1, kwargs) # A lot of different ways to pass the same data foo('a', *(1, 2), kwarg_1=True, other_kwarg=True, y=1) foo('a', *(1, 2), other_kwarg=True, kwarg_1=True, y=1) foo('a', *(1, 2), other_kwarg=True, y=1) foo('a', *[1, 2], **dict(other_kwarg=True, y=1)) foo('a', *[1, 2], **dict([('other_kwarg', True), ('y', 1)])) kwargs = { 'other_kwarg': True, 'y': 1, } args = (1, 2) foo('a', *args, **kwargs) # a (1, 2) True {'other_kwarg': True, 'y': 1} is printed 6 times to the console # Some of these are for demonstration purposes, use the one that is most readable

Nüüd tasub vaadata Python3 sisseehitatud printimise funktsiooni deklaratsiooni ja aru saada kuidas see tegelikult toimib def print(self, *args, sep=' ', end='\n', file=None).