ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 03.12.2023
Просмотров: 396
Скачиваний: 1
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
134
Глава 6.Написание питонического кода
Модуль Python timeit позволяет быстро профилировать время выполнения кода; это всегда лучше, чем просто предположить, что какой-то код работает быстрее.
И хотя многие программисты на Python используют конструкцию range(len())
для циклов for
, функция enumerate()
предоставляет более чистый синтаксис для получения индекса и значения при переборе последовательности. Аналогичным образом команда with предоставляет более чистый и надежный механизм работы с файлами по сравнению с ручными вызовами open()
и close()
. Команда with гарантирует, что метод close()
будет вызван в любой ситуации, когда управление выйдет за пределы блока команды with
В Python предусмотрено несколько способов интерполяции строк. Изначально спецификатор преобразования
%s помечал позиции, в которых строки должны вставляться в исходную строку. Современный подход для версии Python 3.6 основан на использовании f-строк. У f-строк строковый литерал помечается префиксом f
, а фигурные скобки отмечают, где в строке могут размещаться строки (или целые выражения).
Синтаксис
[:]
для создания поверхностных копий списков выглядит немного странно и не может однозначно считаться питоническим, но он стал популярен в качестве способа быстрого создания поверхностных копий списков.
У словарей определены методы get()
и setdefault()
для выполнения операций с несуществующими ключами. Также словарь collections.defaultdict использует значение по умолчанию для несуществующих ключей. Так как в Python нет команды switch
, использование словаря позволяет компактно записать эквивалент switch без нескольких команд if
- elif
- else
; при выборе между двумя значениями также можно использовать тернарный оператор.
Цепочка операторов
==
позволяет проверить, что несколько переменных равны друг другу, а оператор in
— проверить, что переменная имеет одно из нескольких возможных значений.
В этой главе были рассмотрены некоторые идиомы языка Python, а также даны рекомендации относительно того, как писать более питонический код. В следующей главе рассматриваются некоторые проблемы и ловушки, в которые часто попадают начинающие.
7
Жаргон программистов
В своем комиксе XKCD «Up Goer Five» (https://xkcd.
com/1133/) создатель веб-комиксов Рэндалл Мунро (Randall
Munroe) показал техническую схему ракеты Saturn V, исполь- зуя только тысячу самых распространенных английских слов.
Технические термины он описал предложениями, понятными даже ребенку. Но также он наглядно продемонстрировал, почему нельзя все объяснять простыми выражениями. «Штуковина, которая по- может людям очень быстро сбежать, если возникла проблема, все горит и они решают не лететь в космос» для непосвященной аудитории более понятна, чем «запуск системы эвакуации». Однако для инженеров NASA в их повседневной работе все это слишком многословно. Они скорее воспользуются сокращением LES (Launch Escape System).
И хотя компьютерный жаргон может показаться неопытным программистам устра- шающим и запутанным, сокращения необходимы. Некоторые термины в Python и в области разработки программного обеспечения имеют тонкие смысловые разли- чия, и даже опытные разработчики иногда ошибочно используют их как синонимы.
Технические определения таких терминов могут различаться в разных языках про- граммирования, но здесь я рассказываю о терминах в Python. Вы получите широкое, хотя и не глубокое понимание стоящих за ними концепций языка программирования.
Я полагаю, что вы еще не знакомы с классами и объектно-ориентированным про- граммированием (ООП). Поэтому здесь я кратко расскажу о классах и другом
ООП-жаргоне, а о самом жаргоне более подробно мы поговорим в главах 15–17.
Определения
Когда в одной комнате оказываются хотя бы два программиста, вероятность споров о семантике достигает 100%. Язык динамичен, а люди распоряжаются
136
Глава 7.Жаргон программистов словами, но не наоборот. Некоторые разработчики используют одни и те же термины несколько в разных смыслах, но хорошо знать терминологию все равно полезно. В этой главе я расскажу о терминах и их взаимосвязях. Если вам пона- добится список терминов в алфавитном порядке, обращайтесь к официальному глоссарию Python по адресу https://docs.python.org/3/glossary.html; вы найдете здесь канонические определения
1
Несомненно, некоторые программисты, прочитав определения в этой главе, при- помнят особые случаи или исключения, но придираться можно бесконечно. Эта глава не была задумана как исчерпывающее описание; я дал доступные определения, пусть даже не идеальные. Но всегда можно узнать что-то новое, как это обычно бывает в программировании.
Язык Python и интерпретатор Python
Язык программирования Python обязан своим названием не змее, а британской комедийной группе Monty Python (хотя в документации и учебниках Python ис- пользуются отсылки как к Monty Python, так и к змеям). В области программиро- вания название Python тоже имеет два значения.
Когда мы говорим «Python запускает программу» или «Python выдает исклю- чение», речь идет об интерпретаторе Python (Python interpreter) — программе, которая читает текст из файла
.py и выполняет содержащиеся в нем инструк- ции. Если вы встречаете выражение «интерпретатор Python», то почти всегда подразумевается CPython — интерпретатор Python, сопровождением которого занимается фонд Python Software Foundation, доступный на сайте https://www.
python.org. CPython является реализацией (implementation) языка Python (то есть программой, написанной для выполнения спецификации), однако существуют и другие. Хотя CPython написан на языке программирования C, реализация
Jython написана на Java для выполнения сценариев Python, совместимых с программами Java. PyPy — JIT-компилятор (just-in-time compiler) для Python, компилирующий программы непосредственно в процессе их выполнения, — на- писан на Python.
Все эти реализации выполняют исходный код, написанный на языке программи- рования Python; именно это мы имеем в виду, говоря: «Это программа Python» или «Я изучаю Python». В идеале любой интерпретатор Python способен вы- полнить любой исходный код, написанный на языке Python; тем не менее в ре- альном мире всегда будут существовать небольшие несовместимости и различия
1
В этой главе все термины глоссария даются на русском и в скобках на английском языке. —
Примеч. ред.
Определения
137
между интерпретаторами. CPython называется эталонной реализацией (reference implementation) языка Python, потому что, если существуют различия между тем, как код Python интерпретируется CPython и другим интерпретатором, поведение
CPython считается каноническим и правильным.
Сборка мусора
Во многих ранних языках программисту приходилось приказывать программе вы- делять, а затем освобождать память для структур данных по мере необходимости.
Ручное выделение памяти становилось источником многих ошибок, таких как утечка памяти (когда программист забывал освободить выделенную память) или двойное освобождение (когда программисты освобождали одну и ту же область памяти дважды, что приводило к повреждению данных).
Для предотвращения этих ошибок в Python существует сборка мусора (garbage collection) — механизм автоматического управления памятью, который отсле- живает выделение и освобождение памяти, чтобы программисту не приходилось заниматься этим самому. Сборку мусора можно рассматривать как освобождение памяти, потому что она делает память доступной для новых данных. Например, введите следующую команду в интерактивной оболочке:
>>> def someFunction():
... print('someFunction() called.')
... spam = ['cat', 'dog', 'moose']
>>> someFunction()
someFunction() called.
При вызове someFunction()
Python выделяет память для списка
['cat',
'dog',
'moose']
. Программисту не нужно самостоятельно вычислять, сколько байтов памяти следует запросить, потому что Python делает это автоматически. Сборщик мусора Python освобождает локальные переменные при выходе из функции, чтобы занимаемая ими память стала доступна для других данных. Сборка мусора суще- ственно упрощает программирование и повышает его надежность.
Литералы
Литерал (literal) — текст в исходном коде программы, определяющий фиксиро- ванное типизованное значение. В следующем примере:
>>> age = 42 + len('Zophie')
фрагменты текста
42
и 'Zophie'
определяют два литерала, целый и строковый.
Литерал можно рассматривать как значение, буквально определяемое в исходном
138
Глава 7.Жаргон программистов коде. Только встроенные типы данных могут иметь литеральные значения в ис- ходном коде Python, так что переменная age литеральным значением не является.
В табл. 7.1 приведены примеры литералов Python.
Таблица 7.1. Примеры литералов в Python
Литерал
Тип данных
42
Integer
3.14
Float
1.4886191506362924e+36
Float
"""Howdy!"""
String r'Green\Blue'
String
[]
List
{'name': 'Zophie'}
Dictionary b'\x41'
Bytes
True
Boolean
None
NoneType
Дотошные читатели заметят, что некоторые из моих примеров не являются лите- ралами в соответствии с официальной документацией языка Python. Формально
-5
не является литералом в Python, потому что язык определяет знак «минус» (
-
) как оператор, применяемый к литералу
5
. Кроме того,
True
,
False и
None счита- ются ключевыми словами Python, а не литералами, тогда как
[]
и
{}
называются
индикаторами (displays) или атомами (atoms) в зависимости от того, какую часть официальной документации вы просматриваете. Тем не менее литерал — распро- страненный термин, который будет использоваться профессиональными разработ- чиками во всех этих примерах.
Ключевые слова
В каждом языке программирования существует собственный набор ключевых слов.
Ключевые слова Python образуют набор имен, которые резервируются как часть языка и не могут использоваться как имена переменных (то есть идентификаторы).
Например, создать переменную с именем while не удастся, потому что ключевое слово while зарезервировано для использования в циклах while
. Ниже приводится список ключевых слов Python для версии Python 3.9.
Определения
139
and continue finally is raise as def for lambda return assert del from
None
True async elif global nonlocal try await else if not while break except import or with class
False in pass yield
Следует помнить, что ключевые слова Python всегда записываются на английском языке, они недоступны на других языках. Например, следующая функция содержит идентификаторы, записанные на испанском языке, но ключевые слова def и return остаются записанными на английском.
def agregarDosNúmeros(primerNúmero, segundoNúmero):
return primerNúmero + segundoNúmero
К сожалению, английский язык доминирует в области программирования — и это определенная сложность для 6,5 миллиарда человек, которые на английском не говорят.
1 ... 9 10 11 12 13 14 15 16 ... 40
Объекты, значения, экземпляры и идентичность
Объект (object) представляет некоторый фрагмент данных: число, текст или более сложную структуру данных (такую как список или словарь). Все объекты могут сохраняться в переменных, передаваться в аргументах при вызове функций и воз- вращаться из вызовов функций.
Каждый объект характеризуется значением, идентичностью и типом данных (value, identity и data type). Значение — данные, представляемые объектом (например, целое число 42 или строка 'hello'
). И хотя это создает неоднозначность, некоторые програм- мисты используют термин «значение» как синоним объекта, особенно для простых типов данных (например, целых чисел или строк). Так, переменная, которая содержит данные
42
, является переменной, которая содержит целое значение, но также можно сказать, что это переменная, содержащая целочисленный объект со значением
42
Объект создается с идентичностью — уникальным целым числом, которое можно просмотреть вызовом функции id()
. Например, введите следующий код в интерак- тивной оболочке:
>>> spam = ['cat', 'dog', 'moose']
>>> id(spam)
33805656
140
Глава 7.Жаргон программистов
МЕТАФОРЫ ПЕРЕМЕННЫХ: КОРОБКИ И НАКЛЕЙКИ
Во многих учебниках начального уровня переменные сравниваются с короб- ками, что представляет собой чрезмерное упрощение. Переменную удобно представить как коробку, в которой находится значение (рис. 7.1), но когда речь заходит о ссылках, метафора начинает рассыпаться. В только что рас- смотренном примере в переменных spam и eggs не хранились разные словари; в них хранились ссылки на один словарь, находящийся в памяти компьютера.
Рис. 7.1. Во многих книгах переменные сравниваются с коробками, в которых хранятся значения
В Python все переменные с технической точки зрения являются ссылками, а не контейнерами значений, независимо от их типа данных. Метафора ко- робки проста, но не идеальна. Вместо того чтобы рассматривать переменные как коробки, вы также можете рассматривать переменные как наклейки для объектов в памяти. На рис. 7.2 изображены наклейки для переменных spam и eggs из предыдущего примера.
Рис. 7.2. Переменные также можно представить как наклейки для значений
Определения
141
Так как несколько переменных могут ссылаться на один объект, этот объ- ект будет «храниться» в нескольких переменных. Один объект нельзя положить сразу в несколько коробок, поэтому будет проще использовать метафору наклейки. Дополнительная информация по этой теме содержит- ся в докладе Неда Бэтчелдера (Ned Batchelder) на конференции PyCon
2015, «Facts and Myths about Python Names and Values» (https://youtu.
be/_AEJHKGk9ns).
Переменная spam содержит объект с типом данных списка и значением
['cat',
'dog',
'moose']
. Ее идентичность равна
33805656
, хотя числовое идентифициру- ющее значение вычисляется заново при запуске программы, так что с большой вероятностью вы будете получать разные числа на вашем компьютере.
После того как объект будет создан, его идентичность не изменяется на про- тяжении выполнения программы. Хотя тип данных и идентичность объекта не изменяются во время выполнения, значение объекта может измениться, как мы видим в следующем примере:
>>> spam.append('snake')
>>> spam
['cat', 'dog', 'moose', 'snake']
>>> id(spam)
33805656
Теперь список также содержит элемент 'snake'
. Но как видно по вызову id(spam)
, его идентичность не изменилась — список остался тем же. Но давайте посмотрим, что произойдет, если ввести следующий код:
>>> spam = [1, 2, 3]
>>> id(spam)
33838544
Значение в spam было перезаписано новым объектом списка с новой идентичностью:
33838544
вместо
33805656
. Идентификатор (identifier) (такой как spam
) не следует путать с идентичностью (identity), потому что несколько идентификаторов могут ссылаться на объект. Так, в следующем примере двум переменным присваивается один и тот же словарь:
>>> spam = {'name': 'Zophie'}
>>> id(spam)
33861824
>>> eggs = spam
>>> id(eggs)
33861824
142
Глава 7.Жаргон программистов
Идентичности обоих идентификаторов, spam и eggs
, равны
33861824
, потому что они относятся к одному объекту словаря. Теперь измените значение spam в инте- рактивной оболочке:
>>> spam = {'name': 'Zophie'}
>>> eggs = spam
>>> spam['name'] = 'Al'
❶
>>> spam
{'name': 'Al'}
>>> eggs
{'name': 'Al'}
❷
Как видите, изменения spam
❶
, как по волшебству, также появляются в eggs
❷
Это объясняется тем, что оба идентификатора относятся к одному и тому же объекту.
Если не понимать, что оператор присваивания
=
всегда копирует ссылку, а не объ- ект, можно внести в программу ошибку: вы думаете, что копируете объект, тогда как в действительности копируется ссылка на исходный объект. К счастью, это не создает проблем с неизменяемыми значениями (целыми числами, строками и кортежами) по причинам, которые объясняются в подразделе «Изменяемость и неизменяемость» на с. 143.
Оператор is может использоваться для проверки тождественности, то есть того, что два объекта имеют одинаковую идентичность. С другой стороны, оператор
==
проверяет только равенство значений двух объектов. Можно считать, что x
is y
является сокращенной записью для id(x)
==
id(y)
. Введите следующий фрагмент в интерактивной оболочке, чтобы понять суть различий:
>>> spam = {'name': 'Zophie'}
>>> eggs = spam
❶
>>> spam is eggs
True
>>> spam == eggs
True
>>> bacon = {'name': 'Zophie'}
❷
>>> spam == bacon
True
>>> spam is bacon
False
Переменные spam и eggs ссылаются на один объект словаря
❶
, так что их идентич- ности и значения одинаковы. Но переменная bacon ссылается на другой объект словаря
❷
, хотя он и содержит данные, совпадающие с данными spam и eggs
. Со- впадение данных означает, что bacon содержит то же значение, что и spam и eggs
, но это два разных объекта с двумя разными идентичностями.
Определения
143
Элементы
В Python объект, находящийся в объекте-контейнере (таком как список или сло- варь), также называется элементом (item, element). Например, строки в списке
['dog',
'cat',
'moose']
являются объектами, но они также называются элементами.
Изменяемость и неизменяемость
Как я упоминал ранее, все объекты в Python характеризуются значением, типом данных и идентичностью и из всех этих атрибутов изменяться может только значе- ние. Если значение объекта можно изменить, этот объект называется изменяемым
(mutable). Если значение объекта изменить нельзя, объект называется неизменяе-
мым (immutable). В табл. 7.2 перечислены некоторые изменяемые и неизменяемые типы данных в Python.
Таблица 7.2. Примеры изменяемых и неизменяемых типов данных Python
Изменяемые типы данных
Неизменяемые типы данных
List (Список)
Integer (Целое число)
Dictionaries (Словари)
Floating-point number (Число с плавающей точкой)
Sets (Множества)
Boolean (Логический)
Bytearray (Массив байтов)
String (Строка)
Array (Массив)
Frozen set (Зафиксированное множество)
Bytes (Байты)
Tuple (Кортеж)
Когда вы перезаписываете переменную, может показаться, что вы изменяете зна- чение объекта, как в следующем примере:
>>> spam = 'hello'
>>> spam
'hello'
>>> spam = 'goodbye'
>>> spam
'goodbye'
Но в этом коде вы не заменяете значение объекта 'hello'
значением 'goodbye'
Это два разных объекта, а вы только переключаете переменную spam так, чтобы