Звёздный Python: где и как используются * и ** |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2018-10-27 19:45 В Python много где можно встретить Что мы не собираемся обсуждать Речь пойдёт о префиксных, а не об инфиксных операторах. То есть мы не собираемся обсуждать умножение и возведение в степень: >>> 2 * 5 10 >>> 2 ** 5 32 О чём пойдёт речь Мы обсудим префиксные операторы >>> numbers = [2, 1, 3, 4, 7] >>> more_numbers = [*numbers, 11, 18] >>> print(*more_numbers, sep=', ') 2, 1, 3, 4, 7, 11, 18 Здесь показаны два примера использования
Даже если вы считаете, что вам знакомы все эти способы использования Прим. перев. Примеры кода в статье предполагают использование Python 3. Звёздочки для распаковки в аргументы функции При вызове функции можно использовать оператор >>> fruits = ['lemon', 'pear', 'watermelon', 'tomato'] >>> print(fruits[0], fruits[1], fruits[2], fruits[3]) lemon pear watermelon tomato >>> print(*fruits) lemon pear watermelon tomato Строка Здесь оператор Вот другой пример: def transpose_list(list_of_lists): return [ list(row) for row in zip(*list_of_lists) ] Здесь мы принимаем список со списками и возвращаем «транспонированный» список. >>> transpose_list([[1, 4, 7], [2, 5, 8], [3, 6, 9]]) [[1, 2, 3], [4, 5, 6], [7, 8, 9]] Оператор >>> date_info = {'year': "2020", 'month': "01", 'day': "01"} >>> filename = "{year}-{month}-{day}.txt".format(**date_info) >>> filename '2020-01-01.txt' Начиная с Python 3.5 Порой бывает полезно использовать >>> fruits = ['lemon', 'pear', 'watermelon', 'tomato'] >>> numbers = [2, 1, 3, 4, 7] >>> print(*numbers, *fruits) 2 1 3 4 7 lemon pear watermelon tomato Похожим образом используются >>> date_info = {'year': "2020", 'month': "01", 'day': "01"} >>> track_info = {'artist': "Beethoven", 'title': 'Symphony No 5'} >>> filename = "{year}-{month}-{day}-{artist}-{title}.txt".format( ... **date_info, ... **track_info, ... ) >>> filename '2020-01-01-Beethoven-Symphony No 5.txt' Следует соблюдать осторожность при многократном использовании Звёздочки для упаковки аргументов, переданных в функцию При определении функции можно использовать from random import randint def roll(*dice): return sum(randint(1, die) for die in dice) Эта функция принимает любое количество аргументов: >>> roll(20) 18 >>> roll(6, 6) 9 >>> roll(6, 6, 6) 8 Стандартные функции Python В схожих целях можно применить и def tag(tag_name, **attributes): attribute_list = [ f'{name}="{value}"' for name, value in attributes.items() ] return f"<{tag_name} {' '.join(attribute_list)}>" Оператор >>> tag('a', href="http://example.com") '<a href="http://example.com">' >>> tag('img', height=20, width=40, src="img.jpg") '<img height="20" width="40" src="img.jpg">' Позиционные аргументы с только именованными аргументами В Python 3 появился специальный синтаксис для только именованных (keyword-only) аргументов. Такие аргументы нельзя указать позиционно, только по имени. Чтобы принимать только именованные аргументы, при определении функции мы можем расположить именованные аргументы после def get_multiple(*keys, dictionary, default=None): return [ dictionary.get(key, default) for key in keys ] Эту функцию можно использовать следующим образом: >>> fruits = {'lemon': 'yellow', 'orange': 'orange', 'tomato': 'red'} >>> get_multiple('lemon', 'tomato', 'squash', dictionary=fruits, default='unknown') ['yellow', 'red', 'unknown'] Аргументы >>> fruits = {'lemon': 'yellow', 'orange': 'orange', 'tomato': 'red'} >>> get_multiple('lemon', 'tomato', 'squash', fruits, 'unknown') Traceback (most recent call last): File "", line 1, in TypeError: get_multiple() missing 1 required keyword-only argument: 'dictionary' Такое поведение было добавлено в PEP 3102. Только именованные аргументы без позиционных Описанный выше пример выглядит здорово, но что, если мы хотим получить только именованные аргументы без захвата неограниченного количества позиционных? Прим. перев. Если к этому моменту вы задались вопросом, зачем вообще нужны только именованные аргументы, то всё просто: вызов функции с именованными аргументами выглядит гораздо лучше — сразу можно понять, какой аргумент за что отвечает. Более того, при использовании позиционных аргументов вы вынуждены соблюдать их порядок, в то время как именованные аргументы можно расположить как угодно. Также они позволяют не указывать значения аргументов, у которых есть значения по умолчанию. Python позволяет сделать это с помощью одинокой звёздочки: def with_previous(iterable, *, fillvalue=None): """Yield each iterable item along with the item before it.""" previous = fillvalue for item in iterable: yield previous, item previous = item Эта функция принимает аргумент >>> list(with_previous([2, 1, 3], fillvalue=0)) [(0, 2), (2, 1), (1, 3)] Но не так: >>> list(with_previous([2, 1, 3], 0)) Traceback (most recent call last): File "", line 1, in TypeError: with_previous() takes 1 positional argument but 2 were given Эта функция принимает два аргумента, и один из них, Встроенная функция >>> help(sorted) Help on built-in function sorted in module builtins: sorted(iterable, /, *, key=None, reverse=False) Return a new list containing all items from the iterable in ascending order. A custom key function can be supplied to customize the sort order, and the reverse flag can be set to request the result in descending order. Прим. перев. Нечто аналогичное можно сделать и для позиционных аргументов. Как вы могли заметить, в определении Звёздочки для распаковки В Python 3 также появилась возможность использовать оператор >>> fruits = ['lemon', 'pear', 'watermelon', 'tomato'] >>> first, second, *remaining = fruits >>> remaining ['watermelon', 'tomato'] >>> first, *remaining = fruits >>> remaining ['pear', 'watermelon', 'tomato'] >>> first, *middle, last = fruits >>> middle ['pear', 'watermelon'] Распаковка может быть даже вложенной: >>> fruits = ['lemon', 'pear', 'watermelon', 'tomato'] >>> ((first_letter, *remaining), *other_fruits) = fruits >>> remaining ['e', 'm', 'o', 'n'] >>> other_fruits ['pear', 'watermelon', 'tomato'] Вряд ли вам представится возможность так сделать, но, возможно, это и к лучшему. Tакая функциональность была добавлена в PEP 3132. Звёздочки в литералах списков В Python 3.5 появились новые способы использования звёздочек. Одной из ключевых новых фич являлась возможность сложить итерируемый объект в новый список. Допустим, у вас есть функция, которая принимает любую последовательность и возвращает список, состоящий из этой последовательности и её обратной копии, сконкатенированных вместе: def palindromify(sequence): return list(sequence) + list(reversed(sequence)) Здесь нам требуется несколько раз преобразовывать последовательности в списки, чтобы получить конечный результат. В Python 3.5 можно поступить по-другому: def palindromify(sequence): return [*sequence, *reversed(sequence)] Этот вариант избавляет нас от необходимости лишний раз вызывать Ещё пример: def rotate_first_item(sequence): return [*sequence[1:], sequence[0]] Эта функция возвращает новый список, в котором первый элемент переданного списка (или другой последовательности) перемещается в конец нового списка. Такой вариант использования оператора Мы не ограничены созданием списков. Мы также можем создавать новые кортежи или множества: >>> fruits = ['lemon', 'pear', 'watermelon', 'tomato'] >>> (*fruits[1:], fruits[0]) ('pear', 'watermelon', 'tomato', 'lemon') >>> uppercase_fruits = (f.upper() for f in fruits) >>> {*fruits, *uppercase_fruits} {'lemon', 'watermelon', 'TOMATO', 'LEMON', 'PEAR', 'WATERMELON', 'tomato', 'pear'} Обратите внимание, что в последней строке мы создаём новое множество из списка и генератора. До того как появилась возможность использовать >>> set().union(fruits, uppercase_fruits) {'lemon', 'watermelon', 'TOMATO', 'LEMON', 'PEAR', 'WATERMELON', 'tomato', 'pear'} Двойные звёздочки в литералах словарей В PEP 448 были также добавлены новые возможности для >>> date_info = {'year': "2020", 'month': "01", 'day': "01"} >>> track_info = {'artist': "Beethoven", 'title': 'Symphony No 5'} >>> all_info = {**date_info, **track_info} >>> all_info {'year': '2020', 'month': '01', 'day': '01', 'artist': 'Beethoven', 'title': 'Symphony No 5'} Однако это можно использовать не только для объединения двух словарей. Например, мы можем скопировать словарь, параллельно добавляя в него новое значение: >>> date_info = {'year': '2020', 'month': '01', 'day': '7'} >>> event_info = {**date_info, 'group': "Python Meetup"} >>> event_info {'year': '2020', 'month': '01', 'day': '7', 'group': 'Python Meetup'} Или скопировать/объединить словари, параллельно перезаписывая определённые значения: >>> event_info = {'year': '2020', 'month': '01', 'day': '7', 'group': 'Python Meetup'} >>> new_info = {**event_info, 'day': "14"} >>> new_info {'year': '2020', 'month': '01', 'day': '14', 'group': 'Python Meetup'} Звёздочки — сила Операторы Источник: tproger.ru Комментарии: |
|