Питон звездочка перед параметром

Всё, что вам нужно знать о звёздочках в Python

Большинство разработчиков знают символ звёздочки как оператор умножения в Python:

Однако, звёздочка имеет особое значение для сложных структур данных, например списка или словаря.

*args и **kwargs

*args в объявлении функции

В Python оператор распаковки или оператор * наиболее широко используется в функциях.

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

def add(number_1, number_2): return number_1 + number_2 print(add(1, 2)) # 3

Но что делать, если мы хотим сложить произвольное количество значений? Вы можете просто добавить звёздочку перед именем параметра следующим образом:

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

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

* при вызове функции

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

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

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

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

К счастью, оператор распаковки ( * ) работает в обоих направлениях. Мы уже видели его использование в объявлении функции, но и при вызове функции это тоже сработает:

my_list = [1, 2, 3] add(*my_list)

**kwargs в объявлении функции

Распаковывать словари с помощью оператора ** можно точно так же, как и делали с * .

Рассмотрим следующую функцию:

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

Если вызывать функцию с именованными аргументами, вызов будет выглядеть следующим образом:

change_user_details('pythontalk', email='pythontalk@ya.ru', phone='. ', . )

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

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

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

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

** в вызове функции

Конечно, оператор ** работает и при вызове функции для распаковки аргументов:

details = < 'email': 'pythontalk@ya.ru', . >change_user_detail('pythontalk', **details)

Ограничение способов вызова функций

Только именованные аргументы

Одной из самых прикольных особенностей звёздочки в определениях функций является то, что ее можно использовать автономно, то есть без названия переменной (параметра). И в Python такое определение функции тоже будет абсолютно правильным:

def my_function(*, keyword_arg_1): .

Но что в этом случае делает самостоятельная звёздочка? Звёздочка упаковывает все аргументы (не являющиеся именованными), как мы видели выше. Но в нашем случае у неё нет названия (и ее нельзя использовать), а после * идёт переменная keyword_arg_1 . Поскольку * уже соответствует всем позиционным аргументам, у нас остается keyword_arg_1 , который обязан использоваться в качестве именованного аргумента.

Вызов функции с позиционными аргументами ( my_function(1) ) вызовет ошибку:

TypeError: my_function() takes 0 positional arguments but 1 was given

Только позиционные аргументы

Что, если мы хотим заставить пользователей использовать только позиционные аргументы, в отличие от именованных аргументов в предыдущем примере?

Есть очень простой способ. Мы используем знак / :

def only_positional_arguments(arg1, arg2, /): .

Удивительно, но немногие разработчики знают об этом приёме, который был введён в Python 3.8 с PEP 570 .

Если попытаться вызвать функцию с именованными аргументами only_positional_arguments(arg1=1, arg2=2) , это приведёт к ошибке TypeError.

TypeError: only_positional_arguments() got some positional-only arguments passed as keyword arguments: 'arg1, arg2'

Использование * и ** при создании объектов

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

Создание списков

Допустим, у нас есть два отдельных списка и мы хотим их объединить.

my_list_1 = [1, 2, 3] my_list_2 = [10, 20, 30]

Конечно, мы можем сделать это с помощью оператора + :

merged_list = my_list_1 + my_list_2

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

some_value = 42 merged_list = [*my_list_1, some_value, *my_list_2] # [1, 2, 3, 42, 10, 20, 30]

Создание словарей

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

social_media_details = < 'telegram': 'pythontalk' >contact_details = < 'email': 'pythontalk@ya.ru' >user_dict = #

Распаковка объектов

Возможно, вы уже знаете, как разделить элементы последовательности на несколько переменных следующим образом:

my_list = [1, 2, 3] a, b, c = my_list # a -> 1 # b -> 2 # c -> 3

Но знаете ли вы, что звездочки ( * ) можно использовать для назначения переменных, когда у вас есть последовательность произвольной длины?

Скажем, вам нужен первый элемент и последний элемент списка в определенных переменных.

Вы можете сделать это, используя звездочку следующим образом:

my_list = [1, 2, 3] a, *b, c = my_list

В этом примере a теперь содержит первый элемент, а c — последний элемент my_list . А что же в b ?

В b находится весь список, исключая первый и последний элемент, то есть [2] . Обратите внимание, что b теперь является списком.

Эта идея может стать немного яснее, если мы посмотрим на более крупные списки:

my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] a, *b, c = my_list # a -> 1 # b -> [2, 3, 4, 5, 6, 7, 8, 9] # c -> 10

Источник

Супер-звезда Python. 5 способов использования оператора *.

Символ звездочка ( * ) или астериск, известный как оператор умножения, часто используется в языках программирования. Новичкам достаточно знать его основное применение.

Однако, если Вы собираетесь стать экспертом по Python, то нужно углубить свои знания! Пришло время узнать, насколько полезна и мощна “звездочка” в Python.

В этой статье мы рассмотрим 5 способов использования оператора * с примерами, от элементарных к более сложным.

Способ 1: Умножить или возвести в степень

Самое очевидное — использовать звездочки как математические операторы:

Способ 2: Любое количество аргументов функции

Функция не обязательно должна получать фиксированное количество аргументов.

Предположим, что Вы заранее не знаете, сколько аргументов будет передано. Здесь «звездочки» могут прийти к Вам на помощь!

 
def print_genius(*names): print(type(names)) for n in names: print(n) print_genius('Elon Mask', 'Mark Zuckerberg ', 'Yang Zhou') # class 'tuple' # Elon Mask # Mark Zuckerberg # Yang Zhou def top_genius(**names): print(type(names)) for k, v in names.items(): print(k, v) top_genius(Top1="Elon Mask", Top2="Mark Zuckerberg", Top3="Yang Zhou") # class 'dict' # Top1 Elon Mask # Top2 Mark Zuckerberg # Top3 Yang Zhou

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

  • Параметр с префиксом * может записывать любое количество позиционных аргументов в tuple из аргументов
  • Параметр с префиксом ** может записывать любое количество именованных аргументов и составить из них словарь dict

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

Вообще говоря, вместо args и kwargs может стоять все, что угодно — это просто общепринятое соглашение. Можете написать tea и coffee . Но понятней от этого не станет 🙂

Способ 3: Контроль за именованными аргументами

Еще одно полезное использование звездочек — заставить функцию принимать только именованные аргументы.

 
def genius(*, first_name, last_name): print(first_name, last_name) genius('Yang','Zhou') # TypeError: genius() takes 0 positional arguments but 2 were given genius(first_name='Yang', last_name='Zhou') # Yang Zhou

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

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

 
def genius(age, *, first_name, last_name): print(first_name, last_name, 'is', age) genius(28, first_name='Yang', last_name='Zhou') # Yang Zhou is 28

В данном примере, если бы Вы ввели ‘Yang’ без ключевого слова first_name , то Вы получили бы ошибку.

Ситуация 4: Распаковка объектов

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

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

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

 
A = [1, 2, 3] B = (4, 5, 6) C = 7, 8, 9> L = [] for a in A: L.append(a) for b in B: L.append(b) for c in C: L.append(c) print(L) # [1, 2, 3, 4, 5, 6, 8, 9, 7]

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

 
A = [1, 2, 3] B = (4, 5, 6) C = 7, 8, 9> L = [a for a in A] + [b for b in B] + [c for c in C] print(L) # [1, 2, 3, 4, 5, 6, 8, 9, 7]

Мы сократили три цикла for до одной строки. Это уже хороший код, но способ не самый простой! Можно еще красивей.

Пора посмотреть, насколько красивы в данной ситуации звездочки 🙂

 
A = [1, 2, 3] B = (4, 5, 6) C = 7, 8, 9> L = [*A, *B, *C] print(L) # [1, 2, 3, 4, 5, 6, 8, 9, 7]

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

 
D = 'first': 1, 'second': 2, 'third': 3> print(*D) # first second third # print(**D) # TypeError: 'first' is an invalid keyword argument for print() print(',,'.format(**D)) # 1,2,3

Ситуация 5: Множественное присваивание

Этот синтаксис распаковки был введен в PEP 3132, чтобы сделать наш код более элегантным.

Этот PEP позволяет указать «всеобъемлющее» имя, в который будет помещен весь список элементов, которым не присвоено «обычное» имя.

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

Эпилог

Звездочка — один из наиболее часто используемых операторов в программировании на любом языке. Однако, в Python много интересных конструкций, которыми можно и нужно пользоваться. Это покажет Ваш профессионализм, а также сделает Ваш код более читаемым и качественным.

Источник

Читайте также:  Javascript навигация по странице
Оцените статью