Оператор две звездочки python

Операторы * и ** для упаковки и распаковки коллекций

На этом занятии я хочу немного отступить от темы функций и рассказать об операторах * и **, которые мы затронули на предыдущем уроке.

Мы знаем, что они позволяют упаковывать аргументы в кортеж и словарь. Но их можно использовать не только в объявлении функций, но и при работе с разными коллекциями. Например, если взять кортеж из двух значений:

то его можно распаковать в две переменные. Но, если мы пропишем там больше значений, например, четыре:

то уже получим ошибку, так как элементов четыре, а переменных всего две. Но, используя оператор *, мы можем упаковать оставшиеся значения во вторую переменную:

То же самое можно проделывать и со списками:

И вообще с любыми итерируемыми объектами. То есть, оператор * упаковывает оставшиеся значения в список. Правда, мы не можем упаковывать уже упакованные данные, например, так:

произойдет ошибка, но вот так:

Этот же оператор может выполнять и обратную операцию – распаковывать коллекции в набор данных. Пусть у нас имеется список:

И на его основе мы хотим сформировать кортеж. Если просто записать переменную в круглых скобках:

то увидим кортеж со списком внутри. Но, если прописать оператор * перед списком:

то произойдет распаковка его элементов и список превратится в кортеж. То же самое можно сделать и при вызове функций. Допустим, определим кортеж из двух значений:

и вызовем с этими значениями функцию:

Возникнет ошибка, так как функция ожидает числа в качестве аргументов, а не коллекции. Но, мы можем распаковать кортеж d в два числа, поставив перед ним оператор *:

и теперь никаких ошибок нет. Давайте посмотрим, что вернет эта функция, преобразуем все к списку:

Да, получаем ожидаемые значения от -5 до 5. И, теперь, это же преобразование генератора range() в список мы можем сделать и так:

Здорово, да?! Мы оператором * распаковали итерируемый объект и составили из его значений список.

Мало того, мы таким образом можем делать объединение разных коллекций в одну коллекцию, например, список:

Как видите, оператор * — невероятно удобный инструмент. И те же самые действия можно делать и со словарем. Зададим, следующий словарь с расшифровкой оценок:

d = {0: "безнадежно", 1: "убого", 2: "неуд.", 3: "удовл.", 4: "хорошо", 5: "отлично"}

Распаковать его можно двумя способами. Если прописать один оператор *:

То получим множество, состоящее из ключей этого словаря. Или, можно сформировать список из ключей:

То есть, оператор * перебирает словарь как обычный итерируемый объект и по умолчанию, перебираются именно ключи. Если нам нужно перебрать значения, то следует вызвать дополнительно метод:

и получим список из значений. Соответственно, метод:

вернет кортежи из пары ключ-значение.

Если же требуется распаковать словарь как словарь, то перед ним следует прописать две звездочки:

Теперь вместо множества мы получаем словарь. Где это нам может пригодиться? Например, для объединения нескольких словарей в один. Создадим еще один словарь:

d2 = {6: "превосходно", 7: "элитарно", 8: "божественно"}

И соединим их через распаковку данных:

Читайте также:  Can ids be numbers html

На выходе получаем новый словарь с объединенными данными. Такой прием часто используется на практике, когда нужно объединить сразу несколько словарей. А вот для упаковки оператор ** не используется, если прописать, что то вроде:

то получим синтаксическую ошибку. Можно указывать только одну звездочку. Исключение только параметр **kwargs при определении функций.

Надеюсь, теперь вы знаете, как работают операторы * и ** для упаковки и распаковки коллекций. Закрепляйте все практическими заданиями и переходите к следующему уроку.

Видео по теме

#1. Первое знакомство с Python Установка на компьютер

#2. Варианты исполнения команд. Переходим в PyCharm

#3. Переменные, оператор присваивания, функции type и id

#4. Числовые типы, арифметические операции

#5. Математические функции и работа с модулем math

#6. Функции print() и input(). Преобразование строк в числа int() и float()

#7. Логический тип bool. Операторы сравнения и операторы and, or, not

#8. Введение в строки. Базовые операции над строками

#9. Знакомство с индексами и срезами строк

#11. Спецсимволы, экранирование символов, row-строки

#12. Форматирование строк: метод format и F-строки

#13. Списки — операторы и функции работы с ними

#14. Срезы списков и сравнение списков

#15. Основные методы списков

#16. Вложенные списки, многомерные списки

#17. Условный оператор if. Конструкция if-else

#18. Вложенные условия и множественный выбор. Конструкция if-elif-else

#19. Тернарный условный оператор. Вложенное тернарное условие

#21. Операторы циклов break, continue и else

#22. Оператор цикла for. Функция range()

#23. Примеры работы оператора цикла for. Функция enumerate()

#24. Итератор и итерируемые объекты. Функции iter() и next()

#25. Вложенные циклы. Примеры задач с вложенными циклами

#26. Треугольник Паскаля как пример работы вложенных циклов

#27. Генераторы списков (List comprehensions)

#28. Вложенные генераторы списков

#29. Введение в словари (dict). Базовые операции над словарями

#30. Методы словаря, перебор элементов словаря в цикле

#31. Кортежи (tuple) и их методы

#32. Множества (set) и их методы

#33. Операции над множествами, сравнение множеств

#34. Генераторы множеств и генераторы словарей

#35. Функции: первое знакомство, определение def и их вызов

#36. Оператор return в функциях. Функциональное программирование

#37. Алгоритм Евклида для нахождения НОД

#38. Именованные аргументы. Фактические и формальные параметры

#39. Функции с произвольным числом параметров *args и **kwargs

#40. Операторы * и ** для упаковки и распаковки коллекций

#42. Анонимные (lambda) функции

#43. Области видимости переменных. Ключевые слова global и nonlocal

#45. Введение в декораторы функций

#46. Декораторы с параметрами. Сохранение свойств декорируемых функций

#47. Импорт стандартных модулей. Команды import и from

#48. Импорт собственных модулей

#49. Установка сторонних модулей (pip install). Пакетная установка

#50. Пакеты (package) в Python. Вложенные пакеты

#51. Функция open. Чтение данных из файла

#52. Исключение FileNotFoundError и менеджер контекста (with) для файлов

#53. Запись данных в файл в текстовом и бинарном режимах

#55. Функция-генератор. Оператор yield

#56. Функция map. Примеры ее использования

Читайте также:  Узнать версию пакета питон

#57. Функция filter для отбора значений итерируемых объектов

#58. Функция zip. Примеры использования

#59. Сортировка с помощью метода sort и функции sorted

#60. Аргумент key для сортировки коллекций по ключу

#61. Функции isinstance и type для проверки типов данных

#62. Функции all и any. Примеры их использования

#63. Расширенное представление чисел. Системы счисления

#64. Битовые операции И, ИЛИ, НЕ, XOR. Сдвиговые операторы

#65. Модуль random стандартной библиотеки

#66. Аннотация базовыми типами

#67. Аннотации типов коллекций

#68. Аннотации типов на уровне классов

#69. Конструкция match/case. Первое знакомство

#70. Конструкция match/case с кортежами и списками

#71. Конструкция match/case со словарями и множествами

#72. Конструкция match/case. Примеры и особенности использования

© 2023 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта

Источник

Что такое *args и **kwargs в Python?

Функции — это жизнь. Правда? Если вы только начали осваивать Python, неважно — первый ли это ваш язык программирования, или вы пришли в Python из другого языка, то вы уже знаете о том, что количество параметров в объявлении функции соответствует количеству аргументов, которые передают функции при вызове.

Это — основы. Это то, что помогает людям понимать окружающий мир. Но утверждение «количество параметров равно количеству аргументов» закладывает в голову новичка бомбу замедленного действия, которая срабатывает после того, как он увидит в объявлении функции таинственные конструкции *args или **kwargs .

Не позволяйте всяким значкам загонять себя в ступор. Тут нет ничего архисложного. В общем-то, если эти конструкции вам незнакомы — предлагаю с ними разобраться.

Позиционные и именованные аргументы

Для того чтобы разобраться с *args и **kwargs , нам нужно освоить концепции позиционных (positional) и именованных (keyword) аргументов.

Сначала поговорим о том, чем они отличаются. В простейшей функции мы просто сопоставляем позиции аргументов и параметров. Аргумент №1 соответствует параметру №1, аргумент №2 — параметру №2 и так далее.

def printThese(a,b,c): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored in c") printThese(1,2,3) """ 1 is stored in a 2 is stored in b 3 is stored in c """

Для вызова функции необходимы все три аргумента. Если пропустить хотя бы один из них — будет выдано сообщение об ошибке.

def printThese(a,b,c): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored in c") printThese(1,2) """ TypeError: printThese() missing 1 required positional argument: 'c' """

Если при объявлении функции назначить параметру значение по умолчанию — указывать соответствующий аргумент при вызове функции уже необязательно. Параметр становится опциональным.

def printThese(a,b,c=None): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored in c") printThese(1,2) """ 1 is stored in a 2 is stored in b None is stored in c """

Опциональные параметры, кроме того, можно задавать при вызове функции, используя их имена.

В следующем примере установим три параметра в значение по умолчанию None и взглянем на то, как их можно назначать, используя их имена и не обращая внимания на порядок следования аргументов, применяемых при вызове функции.

def printThese(a=None,b=None,c=None): print(a, "is stored in a") print(b, "is stored in b") print(c, "is stored in c") printThese(c=3, a=1) """ 1 is stored in a None is stored in b 3 is stored in c """

Оператор «звёздочка»

Оператор * чаще всего ассоциируется у людей с операцией умножения, но в Python он имеет и другой смысл.

Читайте также:  @ViewBag.Title

Этот оператор позволяет «распаковывать» объекты, внутри которых хранятся некие элементы. Вот пример:

a = [1,2,3] b = [*a,4,5,6] print(b) # [1,2,3,4,5,6]

Тут берётся содержимое списка a , распаковывается, и помещается в список b .

Как пользоваться *args и **kwargs

Итак, мы знаем о том, что оператор «звёздочка» в Python способен «вытаскивать» из объектов составляющие их элементы. Знаем мы и о том, что существует два вида параметров функций. Вполне возможно, что вы уже додумались до этого сами, но я, на всякий случай, скажу об этом. А именно, *args — это сокращение от «arguments» (аргументы), а **kwargs — сокращение от «keyword arguments» (именованные аргументы).

Каждая из этих конструкций используется для распаковки аргументов соответствующего типа, позволяя вызывать функции со списком аргументов переменной длины. Например — создадим функцию, которая умеет выводить результаты, набранные учеником в тесте:

def printScores(student, *scores): print(f"Student Name: ") for score in scores: print(score) printScores("Jonathan",100, 95, 88, 92, 99) """ Student Name: Jonathan 100 95 88 92 99 """

Я не использовал при объявлении функции конструкцию *args . Вместо неё у меня — *scores . Нет ли тут ошибки? Ошибки здесь нет. Дело в том, что «args» — это всего лишь набор символов, которым принято обозначать аргументы. Самое главное тут — это оператор * . А то, что именно идёт после него, особой роли не играет. Благодаря использованию * мы создали список позиционных аргументов на основе того, что было передано функции при вызове.

После того, как мы разобрались с *args , с пониманием **kwargs проблем быть уже не должно. Имя, опять же, значения не имеет. Главное — это два символа ** . Благодаря им создаётся словарь, в котором содержатся именованные аргументы, переданные функции при её вызове.

def printPetNames(owner, **pets): print(f"Owner Name: ") for pet,name in pets.items(): print(f": ") printPetNames("Jonathan", dog="Brock", fish=["Larry", "Curly", "Moe"], turtle="Shelldon") """ Owner Name: Jonathan dog: Brock fish: ['Larry', 'Curly', 'Moe'] turtle: Shelldon """

Итоги

Вот несколько советов, которые помогут вам избежать распространённых проблем, возникающих при работе с функциями, и расширить свои знания:

  • Используйте общепринятые конструкции *args и **kwargs для захвата позиционных и именованных аргументов.
  • Конструкцию **kwarg s нельзя располагать до *args . Если это сделать — будет выдано сообщение об ошибке.
  • Остерегайтесь конфликтов между именованными параметрами и **kwargs , в случаях, когда значение планируется передать как **kwarg -аргумент, но имя ключа этого значения совпадает с именем именованного параметра.
  • Оператор * можно использовать не только в объявлениях функций, но и при их вызове.

Источник

Оцените статью