Как сделать или в питоне
Операторы (operators) * и ** встречаются в питоне очень часто. Иногда они немного непонятны и новичкам, и опытным ребятам, переходящим на питон с ряда других языков программирования (в которых операторы могут использоваться немного иначе). Статья известного питон-коуча Трея Ханнера (Trey Hunner), который помогает девелоперам расширять свои знания. Дата написания статьи: 10.11.2018.
Функционал операторов * и ** развивается уже много лет. Я хочу рассмотреть все способы их использования по состоянию на текущий момент. Буду указывать, что конкретно работает только в современных версиях питона. Поэтому, если вы изучали операторы * и ** еще во времена питона 2 (Python 2), советую хотя бы проглядеть данную статью, потому что в питоне 3 (Python 3) этим операторам добавили много новых возможностей.
Если вы начали изучать питон недавно и еще не освоили аргументы ключевых слов (keyword arguments; также известные как именованные аргументы, named arguments), предлагаю сперва прочитать мою статью про аргументы ключевых слов в питоне.
Что мы обсуждать не будем
В данной статье, говоря про операторы * и **, я имею в виду операторы-префиксы (prefix operators), а не инфиксы (infix). То есть, функции умножения и возведения в степень не входят в тему статьи.
Тогда про что же мы говорим
Мы говорим про операторы-префиксы * и **, которые используются перед переменной (variable). Например:
>>> numbers = [2, 1, 3, 4, 7]
>>> more_numbers = [*numbers, 11, 18]
>>> print(*more_numbers, sep=', ')
2, 1, 3, 4, 7, 11, 18
В данном коде можно увидеть два способа использования оператора *. Оператор ** отсутствует.
В сферу применения рассматриваемых операторов входит:
1. Операторы * и **: передача аргументов в функцию.
2. Операторы * и **: захват аргументов, переданных в функцию.
3. Оператор *: принятие аргументов, содержащих только ключевые слова.
4. Оператор *: захват элементов во время распаковки кортежа (tuple).
5. Оператор *: распаковка итерируемых объектов в списке или кортеже.
6. Оператор **: + распаковка словарей в других словарях.
Даже если вам кажется, что вы освоили все эти способы, позволяющие использовать операторы * и **, рекомендую посмотреть на все нижеприведенные блоки кода, чтобы убедиться, что они все вам знакомы. Последние несколько лет разработчики ядра питона продолжают добавлять этим операторам новые возможности, поэтому какие-то из новых применений можно проглядеть.
Операторы * и ** при распаковке во время вызова функции
При вызове функции оператор * можно задействовать для распаковки итерируемого объекта в аргументах, введенных для вызова:
>>> fruits = ['lemon', 'pear', 'watermelon', 'tomato']
>>> print(fruits[0], fruits[1], fruits[2], fruits[3])
lemon pear watermelon tomato
>>> print(*fruits)
lemon pear watermelon tomato
В строке print(*fruits) производится вызов всех элементов списка fruits в функции print. Они становятся отдельными аргументами. При этом нам даже не надо знать, сколько всего аргументов окажется в списке.
Еще один пример:
Функционал оператора ** примерно такой же, просто он применяется к аргументам ключевых слов. Он позволяет нам взять словарь, содержащий пары из ключей и значений, и распаковать его в аргументы ключевых слов при вызове функции.
Скажу из своего опыта. Оператор ** не часто используется для распаковки аргументов ключевых слов при вызове функции. Чаще всего я вижу такие примеры при работе с наследованием: вызовы super() часто включают в себя оба оператора.
Операторы * и ** можно использовать неоднократно при вызове функции. Данная возможность появилась в питоне 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
Неоднократное использование ** выглядит примерно так же:
Однако не нужно терять бдительности при неоднократном использовании операторов * и **. Неоднократное указание одного и того же аргумента ключевых слов не допускается в функциях питона. Поэтому, если использовать ** для словарей, то ключи должны быть уникальными. В противном случае возникнет исключение.
Операторы * и ** при упаковке аргументов, переданных функции
При определении тела функции можно использовать оператор *, чтобы захватывать неограниченное количество позиционных аргументов, переданных этой функции. Они оформляются в кортеж.
Данная функция принимает любое количество аргументов.
Функции питона print и zip принимают любое количество позиционных аргументов. Такое использование оператора * при упаковке аргументов позволяет нам создавать свои функции, которые (аналогично print и zip) принимают любое количество аргументов.
Кроме того, для оператора ** в данном вопросе предусмотрена еще одна возможность: его можно использовать при определении тела функции, позволяющей захватить в словарь любые аргументы ключевых слов, переданные этой функции:
def tag(tag_name, **attributes):
attribute_list = [
f'=""'
for name, value in attributes.items()
]
return f" "
В данном месте ** захватывает в словарь аргументы ключевых слов, которые мы передаем данной функции. Впоследствии аргументы атрибутов (attributes) данной функции смогут на него ссылаться.
>>> tag('a', href="http://treyhunner.com")>>> tag('img', height=20, width=40, src="https://kirill-sklyarenko.ru/face.jpg")
Позиционные аргументы, содержащие аргументы только из ключевых слов
питон 3 ввел специальный синтаксис для передачи аргументов, содержащих только ключевые слова, в функцию. Они представляют собой такие аргументы функции, которые можно определить только с помощью синтаксиса для ключевых слов. Это означает, что их нельзя определить позиционно.
Чтобы принимать аргументы, содержащие только ключевые слова, мы можем поместить именованные аргументы после оператора * при определении тела функции:
def get_multiple(*keys, dictionary, default=None):
return [
dictionary.get(key, default)
for key in keys
]
Данную функцию можно использовать так:
Аргументы dictionary и default поставлены после *keys. То есть, их можно только в качестве аргументов ключевых слов. Если мы попытаемся определить их позиционно, то увидим ошибку:
>>> 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''lemon':>
Данное поведение внедрено в питон с помощью предложения PEP 3102.
Аргументы, содержащие только ключевые слова и не содержащие позиционные аргументы
Аргументы, содержащие только ключевые слова, – неплохое средство. Но что если вы хотите требовать ввода аргументов, содержащих только ключевые слова, не захватывая неограниченное количество позиционных аргументов?
питон позволяет сделать это с помощью немного странного синтаксиса, когда оператор * как бы сам по себе:
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
Данная функция принимает аргумент, содержащий итерируемый объект (iterable). Его можно определить позиционно (то есть, первым) или с помощью названия и аргумента fillvalue, который входит в число аргументов, допускающих только ключевые слова. Это означает, что мы можем вызвать функцию with_previous вот так:
>>> 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
Данная функция принимает два аргумента. Один из них, fillvalue, обязательно определяется как аргумент, содержащий ключевое слово.
Обычно я использую аргументы, допускающие только ключевые слова, при захвате неопределенного количества позиционных аргументов. Но иногда я использую данную возможность оператора *, чтобы форсировать исключительно позиционное определение аргумента.
На самом деле, данный подход используется встроенной функцией питона sorted. Если посмотреть справку для sorted, можно увидеть следующее:
>>> 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.
Пример использования оператора * как самого по себе прямо в документации по аргументам функции sorted.
Операторы * и ** при распаковке кортежа
Дополнительно к вышенаписанному, в питоне 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']
Если вы задаете себе вопрос: как же мне использовать это в своем коде, посмотрите примеры в моей статье про распаковку кортежей в питоне. В этой статье я показал, каким образом такое использование оператора * может, в некоторых случаях, стать альтернативой для срезания последовательностей (sequence slicing).
Обычно во время своих лекций об операторе * я говорю, что можно использовать только одно выражение с ним в отдельном вызове многократного присвоения (multiple assignment). Технически это некорректно, потому что можно его использовать два раза при вложенной распаковке (nested unpacking). Данный вопрос я рассмотрел подробно в статье про распаковку кортежей.
>>> fruits = ['lemon', 'pear', 'watermelon', 'tomato']
>>> ((first_letter, *remaining), *other_fruits) = fruits
>>> remaining
['e', 'm', 'o', 'n']
>>> other_fruits
['pear', 'watermelon', 'tomato']
Правда, я никогда не встречал хорошего примера такого использования. Не думаю, что стал бы его рекомендовать, даже если бы удалось найти. Он выглядит немного непонятно.
Данная возможность добавлена в питон на основе предложения PEP 3132. Следует отметить, что оно не относится к очень длинным.
Операторы * и ** в литерале списка
В питоне 3.5 добавлено очень много возможностей, связанных с оператором *, на основе предложения PEP 448. Одной из самых заметных новых возможностей стало использование * для вывода итерируемого объекта в новый список.
Допустим, у вас есть функция, которая принимает любые последовательности и возвращает список, содержащий каскад из последовательности и ее реверсивного варианта:
Данная функция должна пару раз провести конвертацию в список, чтобы объединить списки и вернуть результат. Начиная с питона 3.5, мы можем, вместо вышеприведенного примера, написать следующее:
В данном коде больше нет нескольких ненужных вызовов списков. Поэтому он стал эффективнее и лучше читается.
Данная функция возвращает новый список, в котором первый элемент переданного списка (или другой последовательности) перенесен в конец нового списка.
Это очень удачная возможность, позволяющая с помощью оператора * объединять итерируемые объекты различных типов. Оператор * работает с любыми итерируемыми объектами, а оператор + работает только с определенными последовательностями, при чем все из объединяемых должны быть одного типа.
Отмечу, что данная возможность не ограничивается только созданием списков. Мы можем выводить итерируемые объекты в новые кортежи или множества (set):
Обратите внимание, что последняя строка принимает список и генератор (generator), а потом выводит их в новое множество. Перед появлением этой возможности для оператора * было непросто сделать это в одну строку кода. Разумеется, способ сделать это существовал, но его было непросто вспомнить или обнаружить:
Оператор ** в литерале словаря
Помимо вышеприведенного на основе предложения PEP 448 в функционал ** добавлен вывод пар ключ/значение (key/value) из словаря в новый словарь:
Про это я написал еще одну статью. Сейчас ее можно найти под новым названием про идиоматический способ сливать словари в питоне. Данную возможность можно использовать не только для сливания двух словарей. Например, можно скопировать словарь, параллельно добавляя в него новые значения:
Еще можно скопировать или слить словари, переписывая определенные значения:
Операторы * и ** обладают немалыми возможностями в питоне
В питоне операторы * и ** – не просто синтактический выверт. Некоторые из их возможностей реализуются и другими средствами, но доступные альтернативы обычно более громоздкие и потребляют больше ресурсов. Кроме того, некоторые элементы в функционале этих операторов попросту не доступны без их использования. Например, без помощи * невозможно передать в функцию неопределенное количество позиционных аргументов.
Чаще всего я называю их звездой (star) и двойной звездой (double star) (или звездой-звездой (star star)). В данном случае разделения с их функциями как инфиксов не проводится (речь идет про операции умножения и возведения в степень). Но обычно из контекста очевидно, о чем идет речь, про префиксы или инфиксы.
Если вы не понимаете операторы * и ** или боитесь не запомнить все их возможности, не нужно беспокоиться. Способов использования много, и запоминать каждую конкретную возможность для каждого из них не так важно. Лучше будет осознать, в каких случаях к ним можно обратиться. Предлагать использовать данную статью как чек-лист или создать свой чек-лист, который поможет вам использовать операторы * и ** в питоне.
Комментарий может занимать всю строчку:
или может находиться на строчке после какого-нибудь кода:
Внимание: любую строку можно превратить в комментарий, достаточно в начале строки набрать комбинацию клавиш Ctrl+/
Числа
Числа в Python бывают трёх типов:
Строки
Строка – это последовательность символов. Чаще всего строки – это просто некоторые наборы слов. Слова могут быть как на английском языке, так и почти на любом языке мира.
Кавычки
Строку можно указать, используя одинарные кавычки, как например, 'Это строка'. Любой одиночный символ в кавычках, например, 'ю' — это строка. Пустая строка '' — это тоже строка. То есть строкой мы считаем всё, что находится внутри кавычек.
Запись строки в одинарных кавычках это не единственный способ. Можно использовать и двойные кавычки, как например, ''Это строка''. Для интерпретатора разницы между записями строки в одинарных и двойных кавычках нет.
Внимание :
Если строка началась с двойной кавычки — значит и закончиться должна на двойной кавычке.
Если внутри строки мы хотим использовать двойные кавычки, то саму строку надо делать в одинарных кавычках.
Театр '' Современник ' '
print ('Театр '' Современник '' ')
Строка, занимающая несколько строк, должна быть обрамлена тройными кавычками ( '' '' '' или ''' ). Например:
'''В Python можно использовать одинарные,
двойные и тройные кавычки,
чтобы обозначить строку'''
Отступы
Сдвиг строки с помощью пробелов называется отступами .
Оператор присваивания
Переменная – это именованная область памяти, в которой хранятся данные. Данные помещаются в эту область памяти, как в ящик, с помощью оператора присваивания. Общая форма записи операции присваивания:
Знакомый нам знак равно (=) в программирование это знак операции присваивания. Различие между знаками равно и присваивания в следующем.
Например:
В обычной математической записи выражение b (рано) = b + 2 является не верным. Однако запись оператора присваивания b (присвоить) = b + 2 правильная и означает следующее: к текущему значению переменной b, например, оно было равно 4, прибавляется число 2 , и после выполнения данного оператора, значение переменной будет равно 6.
Основные операторы
Оператор
Краткое описание
Сложение (сумма x и y)
Вычитание (разность x и y)
Умножение (произведение x и y)
Внимание! Если x и y целые, то результат всегда будет целым числом! Для получения вещественного результата хотя бы одно из чисел должно быть вещественным. Пример: 40/5 -> 8, а вот 40/5.0 -> 8.0
y+=x; эквивалентно y = y + x;
y-=x; эквивалентно y = y - x;
y*=x; эквивалентно y = y * x;
y/=x; эквивалентно y = y / x;
y%=x; эквивалентно y = y % x;
больше или равно
меньше или равно
Деление по модулю - деление, в котором возвращается остаток.
4 % 2 в результате будет 0
5 % 2 в результате будет 1
Целочисленное деление - деление, в котором возвращается целая часть результата. Часть после запятой отбрасывается
4 // 3 в результате будет 1
25 // 6 в результате будет 4
Возведение в степень
5 ** 2 в результате будет 25
логическое отрицание НЕ
Основные типы данных
Имя
Тип
Описание
int
float
str
Последовательность символов: " abc " , " pyhton " , " 123 "
list
Последовательность объектов: [ 1, 2.0, " Привет! " ]
dist
tuple
Последовательность неизменных объектов:(20,25 )
set
Последовательность уникальных объектов:
bool
Логические значения: True или False
Список
Список (list) представляет тип данных, который хранит набор или последовательность элементов.
Для создания списка в квадратных скобках [ ] через запятую перечисляются все его элементы.
Создание пустого списка
Создание списка чисел:
Создание списка слов:
Создание списка из элементов разного типа
Для управления элементами списки имеют целый ряд методов. Некоторые из них:
Кроме того, Python предоставляет ряд встроенных функций для работы со списками:
Генераторы
Для создания списков, заполненных по более сложным формулам можно использовать генераторы: выражения, позволяющие заполнить список значениями, вычисленными по некоторым формулам.
Общий вид генератора следующий :
Прим ер. Создать список чисел от 0 до 10
[ i for i in range ( 0 , 10 )]
Вся конструкция заключается в квадратные скобки, потому что будет создан список. Внутри квадратных скобок можно выделить три части:
1) что делаем с элементом i : просто добавляем значение i в список
2) что берем: берем i
3) откуда берем : из объекта range .
Части отделены друг от друга ключевыми словами for и in .
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Пример . Создать список заглавных букв английского алфавита. Код символа ' A ' – 65, код символа ' Z ' – 91. Поскольку символы идут подряд, то возможно использовать генератор.
что делаем: к значению элемента i применяем функцию chr ( i ).
Внимание. Функция chr ( i ) – по числовому коду символа возвращает сам символ. Пример. chr (65) даст символ ' A '.
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
Пример. Создать список строчный букв английского алфавита. Код символа 'a' – 97, код символа 'z' – 123. Поскольку символы идут подряд, то возможно использовать генератор.
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
Библиотека math
Для проведения вычислений с действительными числами язык Python содержит много дополнительных функций, собранных в библиотеку, которая называется math . Для использования этих функций в начале программы необходимо подключить библиотеку, что делается командой
После подключения программа получает доступ ко всем функциям, методам и классам, содержащимся в нём. После подключения можно вызвать любую функцию из подключенной библиотеки по следующему правилу: указывается имя модуля и через точку имя функции
Можно подключать не весь модуль, а какую-то его часть. Например, программист хочет использовать только одну функцию из математической библиотеки math . Если он подключит всю библиотеку, то будет добавлено более 40 функций, которые будут занимать место. Чтобы добавить в проект какую-то часть, используют ключевое слово from :
Ниже приведен список основных функций модуля math . Некоторые из перечисленных функций ( int , round , abs ) являются стандартными и не требуют подключения модуля math для использования.
Функция
Описание
Округление
int(x)
Округляет число в сторону нуля. Это стандартная функция, для ее использования не нужно подключать модуль math .
round(x)
Округляет число до ближайшего целого. Если дробная часть числа равна 0.5, то число округляется до ближайшего четного числа.
round(x, n)
Округляет число x до n знаков после точки. Это стандартная функция, для ее использования не нужно подключать модуль math .
floor(x)
ceil(x)
abs(x)
Модуль (абсолютная величина). Это — стандартная функция.
Корни, логарифмы
sqrt(x)
Квадратный корень. Использование : sqrt(x)
log(x)
Натуральный логарифм. При вызове в виде log(x, b) возвращает логарифм по основанию b .
e
Основание натуральных логарифмов e = 2,71828.
Тригонометрия
sin(x)
Синус угла, задаваемого в радианах
cos(x)
Косинус угла, задаваемого в радианах
tan(x)
Тангенс угла, задаваемого в радианах
asin(x )
Арксинус, возвращает значение в радианах
acos(x)
Арккосинус, возвращает значение в радианах
atan(x)
Арктангенс, возвращает значение в радианах
atan2(y, x)
Полярный угол (в радианах) точки с координатами (x, y).
degrees(x)
Преобразует угол, заданный в радианах, в градусы.
radians(x)
Преобразует угол, заданный в градусах, в радианы.
pi
Константа p = 3.1415.
Генерация случайных чисел (модуль random)
Python порождает случайные числа на основе формулы, так что они на самом деле не случайные, а, как говорят, псевдослучайные.
Модуль random позволяет генерировать случайные числа и имеет большое множество важных для практики функций. Рассмотрим основные функции:
Функция random . random () случайное число от 0 до 1.
На сайте Poromenos' Stuff была
опубликована статья, в которой, в сжатой форме,
рассказывают об основах языка Python. Я предлагаю вам перевод этой статьи. Перевод не дословный. Я постарался подробнее объяснить некоторые моменты, которые могут быть непонятны.
Если вы собрались изучать язык Python, но не можете найти подходящего руководства, то эта
статья вам очень пригодится! За короткое время, вы сможете познакомиться с
основами языка Python. Хотя эта статья часто опирается
на то, что вы уже имеете опыт программирования, но, я надеюсь, даже новичкам
этот материал будет полезен. Внимательно прочитайте каждый параграф. В связи с
сжатостью материала, некоторые темы рассмотрены поверхностно, но содержат весь
необходимый метриал.
Основные свойства
Python не требует явного объявления переменных, является регистро-зависим (переменная var не эквивалентна переменной Var или VAR — это три разные переменные) объектно-ориентированным языком.
Синтаксис
Структуры данных
Python содержит такие структуры данных как списки (lists), кортежи (tuples) и словари (dictionaries). Списки — похожи на одномерные массивы (но вы можете использовать Список включающий списки — многомерный массив), кортежи — неизменяемые списки, словари — тоже списки, но индексы могут быть любого типа, а не только числовыми. "Массивы" в Python могут содержать данные любого типа, то есть в одном массиве может могут находиться числовые, строковые и другие типы данных. Массивы начинаются с индекса 0, а последний элемент можно получить по индексу -1 Вы можете присваивать переменным функции и использовать их соответственно.
Строки
Операторы
Операторы while, if, for составляют операторы перемещения. Здесь нет аналога оператора select, так что придется обходиться if. В операторе for происходит сравнение переменной и списка. Чтобы получить список цифр до числа — используйте функцию range( ). Вот пример использования операторов
while rangelist[ 1 ] == 1 :
pass
Функции
Классы
class Myclass:
common = 10
def __init__( self ):
self .myvariable = 3
def myfunction( self , arg1, arg2):
return self .myvariable
Исключения
Исключения в Python имеют структуру try-except [exceptionname]:
Импорт
randomint = random .randint( 1 , 100 )
>>> print randomint
64
Работа с файловой системой
Особенности
Эпилог
Разумеется в этой статье не описываются все возможности Python. Я надеюсь что эта статья поможет вам, если вы захотите и в дальнейшем изучать этот язык программирования.
Совсем недавно Python 3.8 представил оператор присвоения с двоеточием := , аналогичный оператору присвоения = . Использование этого оператора позволяет ускорить и сократить код.
Эта нотация берёт своё начало в математике. При записи уравнений можно написать что-то вроде a=5, a+b=7. Тогда, используя простую алгебраическую операцию, легко вычислить, что b=2. В этом контексте знак равенства означает тождество. Переменные a и b являются постоянными числами, и, хотя их значение неизвестно при инициализации задачи, они существуют и не изменяются.
С другой стороны, в матема т ике существует другая нотация для обозначения отношения ‘x определяется как y’. Запись x := y не означает, что x и y равны друг другу. Здесь x определён как любое значение y. Уравнение скорее одностороннее, чем симметричное, что несколько сложно понять. Эта нотация применяется только для длинных списков определений переменных в узкоспециализированных научных статьях.
Однако в самой последней версии Python 3.8 стало общепринятым использование := или оператора “морж” (он действительно похож на голову лежащего моржа). С его помощью можно определить переменную в границах выражения в контексте программирования.
Так разработчики Python обосновали введение оператора “морж”:
Это очень технический способ выразить простую идею, которая вскоре станет более понятна. Давайте посмотрим на оператор “морж” в действии.
Рассмотрим следующий код с функцией f , определённой как f = lambda x : x+2 , которая просто прибавляет 2 к любым введённым данным:
Получим [3, 5, 6] , поскольку эти результаты функции не равны 4. Это значительно более эффективная реализация, чем её альтернатива, дважды прогоняющая введённые данные через функцию:
Будьте осторожны: поскольку версия 3.8 является совсем новой, некоторые не обновлённые среды могут не поддерживать её.
Давайте рассмотрим другой пример. Есть некий текстовый файл text.txt . Он содержит три строки с буквами от a до i .
Допустим, мы хотим пройти циклом по файлу строка за строкой. Существует несколько способов сделать это. Например, использовать встроенную функцию .readlines() .
И это неплохое решение — оно делает то, что нужно. Но что, если у вас нет возможности использовать встроенные функции? Не для всех приложений это доступно. Тогда возьмём следующее решение, которое разбивает текст на строки:
Оно тоже работает, но составные функции не настолько просты и понятны, как могли бы быть. Запишем с помощью оператора “морж”:
Здесь мы просто определяем chunk как чтение файла. Просто, коротко и чисто. С другой стороны, запись while chunk = open… была бы неверной, потому что нельзя создавать присвоение переменных при вычислении отдельного выражения.
В качестве следующего примера возьмём заданное выше определение функции f(x), добавлявшей двойку к вводу. Следующая конструкция списка g полностью допустима с использованием оператора “морж”:
Здесь y определяется как f(3) и используется в том же выражении. Нельзя написать что-то вроде g = [y=f(3), …] , поскольку присвоение переменных с использованием = должно выполняться отдельной строкой, а не внутри другого выражения. С помощью стандартного оператора равенства то же самое записывается в две строки:
Теперь использование оператора морж должно быть довольно ясным.
Оператор := может использоваться для присвоения переменных во время вычисления другого выражения.
Поскольку присвоение переменной в форме var = expr должно записываться в отдельной строке, оператор “морж” позволяет сократить пространство, запуская присвоение переменной с выполнением внутри другого выражения, будь то создание списка или чтение файла.
Во многих случаях оператор := аналогичен определению переменных-заполнителей, например for i in range(x): , в котором переменная i инициализируется внутри выражения цикла for. Его можно рассматривать как расширение или обобщение этих “инициализаций скрытых переменных”.
Конечно, оператор “морж” нельзя использовать везде. Следующее недопустимо:
Давайте разберём, почему работает выражение a=(b:=4) . Это происходит потому, что b:=4 не только устанавливает b равным четырём, но и возвращает его значение. Поэтому работает и приведённый выше оператор генератора списков ( if y := f(x)) is not 4] ). Он вычисляет b:=4 как выражение, возвращающее значение, в итоге и a , и b имеют значение 4.
Со скобками вокруг первого оператора (a := 3) он выполняется корректно, потому что использование скобок помечает всё внутри них как выражение. Операторы “морж” могут использоваться только внутри других выражений.
Давайте немного выйдет за пределы каноничного Python. Здесь мы рассмотрим некоторые полезные способы использования оператора “морж”, которые могут привести в ярость фанатичных последователей Python.
Рассмотрим функцию exponent , которая увеличивает base по exp .
Допустим, нам нужно получить значение четырёх в кубе, сохранив при этом значение степени (3). Воспользуемся оператором “морж”:
Тройка сохраняется в хранилище переменных, функция выполняется нормально, мы сэкономили строку кода и некоторое время выполнения. При широкомасштабном использовании оператора “морж” эта экономия заметно ощутима.
Оператор “морж” можно использовать даже в операторах if. В примере ниже (placeholder:=x) вычисляется независимо от значения x . Если выход равен четырём, он всё равно сохраняется в плейсхолдере. Обычно такое использование не имеет особой практической ценности, поскольку выполняется избыточное присваивание (что если x!=4 ?), но полезно знать, что такое возможно.
В качестве ещё одного примера кода не в стиле Python, рассмотрим следующую допустимую функцию:
f(3) возвращает 20, потому что (m := x+1) оценивается как 4 и (m**2) оценивается как 16 . Их сумма равна 20, это вычисляется довольной чистым, но при этом несколько хитрым методом.
Читайте также: