Одной из распространенных сфер, где применяются упаковка и распаковка - это параметры функций. Так, в определениях различных функций нередко можно увидеть, что они
принимают такие параметры как *args
и **kwargs
.
Термины args и kwargs — это соглашения по программированию на Python, в реальности вместо них можно использовать любые именования. *args представляет параметры, которые передаются по позиции. А **kwargs означает параметры, которые передаются по имени. обозначает аргументы ключевого слова.
Оператор * применяется с любым итерируемым объектом (например, кортежем, списком и строками). Тогда как оператор ** можно использовать только со словарями.
Оператор * позволяет передать в функцию несколько значений, и все они будут упакованы в кортеж:
def fun(*args): # обращаемся к первому элементу кортежа print(args[0]) # выводим весь кортеж print(args) fun("Python", "C++", "Java", "C#")
Здесь функция fun
принимает кортеж значений. При вызове мы можем передать ей различное количество значений. Так, в примере выше передается четыре строки,
которые образуют кортеж. Консольный вывод программы:
Python ('Python', 'C++', 'Java', 'C#')
Благодаря такой возможности мы можем передавать в функцию переменное количество значений:
def sum(*args): result = 0 for arg in args: result += arg return result print(sum(1, 2, 3)) # 6 print(sum(1, 2, 3, 4)) # 10 print(sum(1, 2, 3, 4, 5)) # 15
Оператор ** упаковывает аргументы, переданные по имени, в словарь. Имена параметров служат ключами. Например, определим функцию, которая просто будет выводить все переданные параметры
def fun(**kwargs): print(kwargs) # выводим словарь на консоль fun(name="Tom", age="38", company="Google") fun(language="Python", version="3.11")
Консольный вывод программы:
{'name': 'Tom', 'age': '38', 'company': 'Google'} {'language': 'Python', 'version': '3.11'}
Поскольку аргументы передаются в функцию в виде словаря, то внутри функции через ключи мы можем получить их значения:
def fun(**kwargs): for key in kwargs: print(f"{key} = {kwargs[key]}") fun(name="Tom", age="38", company="Google")
Консольный вывод программы:
name = Tom age = 38 company = Google
Выше было описано, как операторы * и ** применяются для упаковки аругментов в кортеж и словарь соответственно. Но эти же операторы могут использоваться для распаковки.
Сначала рассмотрим ситуацию, где это может пригодиться.Пусть мы передаем в функцию кортеж:
def sum(*args): result = 0 for arg in args: result += arg return result numbers = (1, 2, 3, 4, 5) print(sum(numbers))
Здесь в вызов функции sum передается кортеж. Параметр *args
по сути тоже представляет кортеж, и кажется, все должно работать. Тем не менее
мы столкнемся с ошибкой
TypeError: unsupported operand type(s) for +=: 'int' and 'tuple'
То есть в данном случае кортеж numbers передается как элемент кортежа *args
.
И чтобы элементы кортежа были переданы в кортеж *args
как отдельные значения, необходимо выполнить их распаковку:
def sum(*args): result = 0 for arg in args: result += arg return result numbers = (1, 2, 3, 4, 5) # применяем распаковку - *numbers print(sum(*numbers)) # 15
Здесь при передачи кортежа numbers в функцию sym применяется распаковка: *numbers
Другим случаем распаковки может быть ситуация, когда функция принимает несколько параметров, а мы передаем один кортеж или список:
def print_person(name, age, company): print(f"Name:{name}, Age: {age}, Company: {company}") person =("Tom", 38, "Google") # выполняем распаковку кортежа person print_person(*person) # Name:Tom, Age: 38, Company: Google
В данном случае выражение *person
раскладывает кортеж person на отдельные значения, которые передаются параметрам name, age и company.
Оператор ** применяется для распаковки словарей:
def print_person(name, age, company): print(f"Name:{name}, Age: {age}, Company: {company}") tom ={"name":"Tom", "age":38, "company":"Google"} # выполняем распаковку словаря tom print_person(**tom) # Name:Tom, Age: 38, Company: Google
Здесь выражение **tom
раскладывает словарь на отдельные значения, которые передаются параметрам name, age и company по названию ключей.
Параметры *args
и *kwargs
могут использоваться в функции вместе с другими параметрами. Например:
def sum(num1, num2, *nums): result=num1+num2 for n in nums: result += n return result print(sum(1,2,3)) # 6 print(sum(1,2,3,4)) # 10