Как устроен Python. Как устроен Python. Харрисон. Харрисон Мэтт
Скачать 5.41 Mb.
|
ПРИМЕЧАНИЕ Если вы хотите определить неявную квазиистинность для объектов, опре- деляемых пользователем, это поведение определяется методом .__bool__ Метод может возвращать True или False . Если этот специальный ме- тод не определен, то метод .__len__ проверяется на ненулевое значение. Если и этот метод не определен, объект по умолчанию интерпретируется как True : >>> class Nope: ... def __bool__(self): ... return False >>> n = Nope() >>> bool(n) False Если все это покажется вам непонятным, вернитесь к примеру после того, как прочитаете об этих классах. 12.3. None None является экземпляром NoneType . В других языках также существуют аналогичные конструкции, такие как nil, NULL или undefined. Присва- ивая переменной None , вы тем самым показываете, что переменной еще 102 Глава 12. Комментарии, логические значения и None не было присвоено реальное значение. В логическом контексте None интерпретируется как False : >>> bool(None) False ПРИМЕЧАНИЕ Функция Python при отсутствии команды return по умолчанию возвращает None : >>> def hello(): ... print("hi") >>> result = hello() hi >>> print(result) None ПРИМЕЧАНИЕ None является одиночным (синглетным) экземпляром (то есть в интерпрета- торе Python всегда хранится только одна копия None ). Идентификатор этого значения всегда остается одним и тем же: >>> a = None >>> id(a) 140575303591440 >>> b = None >>> id(b) 140575303591440 Таким образом, любая переменная, содержащая None , указывает на тот же объект, что и любая другая переменная, содержащая None . Обычно для таких переменных используется проверка тождественности оператором is вместо проверки равенства оператором == : >>> a is b True >>> a is not b False Оператор is работает быстрее == и напоминает программисту, что сравнива- ются идентификаторы, а не значения. Также выражение is можно поместить в команду if : 12.5. Упражнения 103 >>> if a is None: ... print("A is not set!") A is not set! Так как None в логическом контексте интерпретируется как False , также возможно такое решение: >>> if not a: ... print("A is not set!") A is not set! Тем не менее будьте осторожны с другими значениями, которые также интер- претируются как False — такими, как 0 , [] или '' (пустая строка). Проверка на None должна осуществляться явно. 12.4. Итоги В этой главе вы узнали о комментариях в языке Python. Комментарии начинаются с символа # , а все последующие символы до конца строки игнорируются. Многострочные комментарии не поддерживаются. Также в этой главе обсуждаются значения True , False и преобразование к логическому типу. Многие значения интерпретируются как True в ло- гическом контексте (например, при использовании в команде if ). Как False интерпретируются нули, None и пустые последовательности. Глава завершается описанием объекта None . Это одиночный объект, обозначающий переменные, значение которых должно быть присвоено в будущем. Он также является результатом функции, которая не воз- вращает значение явно. 12.5. Упражнения 1. Создайте переменную age и присвойте ей свой возраст. Создайте другую переменную — old , которая использует условие для про- верки того, что вы старше 18 лет. Значение old должно быть равно True или False 2. Создайте переменную name и присвойте ей свое имя. Создайте дру- гую переменную — second_half , которая проверяет, находится ли 104 Глава 12. Комментарии, логические значения и None первая буква name во второй половине алфавита. Что необходимо для того, чтобы выполнить сравнение? 3. Создайте список names с именами людей в классе. Напишите код, который выводит сообщение 'The class is empty!' или 'Class has enrollments.' в зависимости от того, содержит ли names хоть одно значение. (В этой главе вы найдете подсказки.) 4. Создайте переменную car и присвойте ей None . Напишите код, ко- торый выводит сообщение 'Taxi for you!' или 'You have a car!' в за- висимости от того, содержит ли car хоть одно значение. ( None не является названием автомобиля.) 13 Условия и отступы В этой главе вы больше узнаете о сравнениях в Python. В коде часто приходится принимать решения по выбору выполняемого пути, поэтому сейчас мы посмотрим, как это делается. Кроме логических литералов True и False для получения логических значений в Python также можно использовать выражения. Если у вас имеется два числа, вы можете сравнить их и проверить, что первое боль- ше второго, или наоборот. Эта задача решается операторами > и < соот- ветственно: >>> 5 > 9 False В следующей таблице перечислены операторы сравнения для создания логических значений: Оператор Описание > Больше < Меньше >= Больше или равно <= Меньше или равно == Равно != Не равно is Объекты тождественны is not Объекты не тождественны 106 Глава 13. Условия и отступы Эти операции могут использоваться с большинством типов. А если вы создадите собственный класс, определяющий соответствующие специ- альные методы, то ваш класс тоже сможет использовать их: >>> name = 'Matt' >>> name == 'Matt' True >>> name != 'Fred' True >>> 1 > 3 False ПРИМЕЧАНИЕ Специальные методы сравнения __gt__ , __lt__ , __ge__ , __le__ , __eq__ и __ne__ соотносятся с > , < , >= , <= , == и != соответственно. Определять все эти методы довольно утомительно и однообразно. Для классов, в которых обычно используются эти сравнения, декоратор класса functools.total_ordering предоставит всю функциональность сравнений при условии определения методов __eq__ and __le__ . Декоратор автоматически сгенерирует остальные методы сравнения. В противном случае необходимо реализовать все шесть методов: >>> import functools >>> @functools.total_ordering ... class Abs(object): ... def __init__(self, num): ... self.num = abs(num) ... def __eq__(self, other): ... return self.num == abs(other) ... def __lt__(self, other): ... return self.num < abs(other) >>> five = Abs(-5) >>> four = Abs(-4) >>> five > four # Случай "меньше" не используется! True Декораторы считаются темой средней сложности. В книге начального уровня они не рассматриваются. 13.1. Объединение условных выражений 107 СОВЕТ Операторы is и is not предназначены для сравнения тождественности (то есть того, что два объекта имеют одинаковые идентификаторы и факти- чески являются одним объектом (а не только имеют одинаковые значения)). Так как None является одиночным объектом и имеет только один идентифи- катор, is и is not могут использоваться с None : >>> if name is None: ... # Инициализация name 13.1. Объединение условных выражений Условные выражения могут объединяться логическими операторами and , or и not Логический оператор Описание x and y Выражение истинно только в том случае, если истинны оба операнда x or y Выражение истинно, если истинным является хотя бы один из операндов not x Логическое отрицание x ( True превращается в False , и наоборот) В следующем простом примере оценка присваивания осуществляется на основании количества набранных баллов — выражение проверяет, лежит ли количество набранных баллов в заданном числовом диапазоне: >>> score = 91 >>> if score > 90 and score <= 100: ... grade = 'A' ПРИМЕЧАНИЕ В таких случаях Python позволяет использовать диапазонную проверку: >>> if 90 < score <=100: ... grade = 'A' 108 Глава 13. Условия и отступы Работают оба стиля проверок, но в других языках программирования диа- пазонные проверки поддерживаются редко. Следующий пример проверяет, входит ли имя name в заданную группу: >>> name = 'Paul' >>> beatle = False >>> if name == 'George' or \ ... name == 'Ringo' or \ ... name == 'John' or \ ... name == 'Paul': ... beatle = True ... else: ... beatle = False ПРИМЕЧАНИЕ В этом примере знак \ в конце строки 'George' or \ указывает, что команда продолжается на следующей строке. Как и во многих языках программиро- вания, в Python условные выражения могут заключаться в круглые скобки. Так как в Python круглые скобки не являются обязательными, многие раз- работчики опускают их, если они не являются строго необходимыми для определения приоритета операторов. Однако у круглых скобок есть еще один нюанс: они подсказывают интерпретатору, что команда еще не завершена и будет продолжена в следующей строке. Это означает, что в следующем примере символ \ не нужен: >>> name = 'Paul' >>> beatle = False >>> if (name == 'George' or ... name == 'Ringo' or ... name == 'John' or ... name == 'Paul'): ... beatle = True ... else: ... beatle = False СОВЕТ Ниже приведена версия проверки принадлежности, которая считается одной из базовых идиом Python. Чтобы проверить, входит ли значение в набор, объедините элементы набора в множество и воспользуйтесь опе- ратором in : 13.3. Команды else 109 >>> beatles = {'George', 'Ringo', 'John', 'Paul'} >>> beatle = name in beatles Множества более подробно рассматриваются в одной из последующих глав. Пример использования ключевого слова not в условной команде: >>> last_name = 'unknown' >>> if name == 'Paul' and not beatle: ... last_name = 'Revere' 13.2. Команды if Логические значения ( True и False ) часто используются в условных ко- мандах. Условная команда, по сути, означает: «если это условие истинно, выполнить блок кода, а если нет — выполнить другой код». Условные команды часто используются в Python. Иногда «команда if » проверяет значения, содержащие логические значения; в других случаях проверя- ются выражения, результат которых интерпретируется как логическое значение. Другая распространенная проверка связана с неявным преоб- разованием к «квазиистинным» или «квазиложным» значениям: >>> debug = True >>> if debug: # Проверка логического значения ... print("Debugging") Debugging 13.3. Команды else Команда else может использоваться в сочетании с командой if . Тело else выполняется только в том случае, если условие if дает результат False Ниже приведен пример объединения команды else с if : >>> score = 87 >>> if score >= 90: ... grade = 'A' ... else: ... grade = 'B' Python вычисляет выражение score >= 90 и получает результат False . Так как условие if было ложным, выполняются команды блока else , а пере- менной grade присваивается значение 'B' 110 Глава 13. Условия и отступы 13.4. Множественный выбор Выбор далеко не всегда ограничивается двумя вариантами. При не- обходимости вы можете добавить промежуточные шаги при помощи ключевого слова elif (сокращение от «else if»). Ниже приведена схема выбора с несколькими вариантами: >>> score = 87 >>> if score >= 90: ... grade = 'A' ... elif score >= 80: ... grade = 'B' ... elif score >= 70: ... grade = 'C' ... elif score >= 60: ... grade = 'D' ... else: ... grade = 'F' Каждая из команд if , elif и else имеет собственный блок кода. Python начинает перебор сверху, пытаясь найти условие с результатом True Обнаружив такое условие, Python выполняет блок, а затем переходит к выполнению кода, следующего за всеми блоками elif и else . Если ни одно из условий if и elif не дает результата True , выполняется блок команды else ПРИМЕЧАНИЕ Команда if может содержать ноль и более команд elif . Наличие команды else не обязательно. Если команда else присутствует, то в команде if она может быть только одна. 13.5. Пробелы Возможно, вы обратили внимание на одну странность: за логическим выражением в команде if следует двоеточие ( : ). Строки, следующие непосредственно после команды if , снабжаются отступом из четырех пробелов. Строки с отступами образуют блок кода, который выполняется в том случае, если выражение if дает результат True 13.5. Пробелы 111 В других языках команда if могла бы выглядеть так: if (score >= 90) { grade = 'A'; } В таких языках границы блоков в командах if обозначаются фигурными скобками ( { } ). Весь код между фигурными скобками выполняется в том случае, если значение score больше либо равно 90. В отличие от таких языков, в Python для обозначения блоков использу- ются два признака: двоеточие ( : ); отступы. Если вы программировали на других языках, понять правила использо- вания отступов в Python будет нетрудно. Все, что от вас потребуется, — заменить левую фигурную скобку ( { ) двоеточием ( : ) и последовательно применять отступы до конца блока. СОВЕТ Что считать «последовательным применением отступов»? Обычно для создания отступов в коде используются либо символы табуляции, либо про- белы. Интерпретатор Python обращает внимание только на единство стиля отступов на уровне файла. Проект может состоять из нескольких файлов, использующих разные схемы отступов, но это было бы глупо. Согласно PEP 8, в Python рекомендуется использовать отступы из четырех пробелов. Если вы начнете смешивать табуляции с пробелами в одном файле, вскоре возникнут проблемы. И хотя пробелы считаются предпочтитель- ными, если вы работаете над кодом, в котором уже используются символы табуляции, лучше действовать последовательно и продолжить использовать символы табуляции в коде. Если вы начнете смешивать табуляции с пробелами, исполняемый файл python3 сообщит об ошибке TabError 112 Глава 13. Условия и отступы 13.6. Итоги В этой главе рассматривается команда if . Эта команда может использо- ваться для создания сколь угодно сложных условий посредством объ- единения выражений операторами and , or и not Также в главе рассматривались блоки, отступы и табуляции/пробелы. При первом знакомстве с Python правило обязательных отступов может показаться досадной помехой. Я сталкивался с людьми, которые так считают, на своих учебных курсах. Но когда я их спрашивал, включают ли они отступы в код на других языках, они отвечали: «Конечно, так код лучше читается». В Python удобочитаемости кода уделяется большое внимание, и правило об отступах помогает в этом. 13.7. Упражнения 1. Напишите команду if , которая проверяет, является ли год, храня- щийся в переменной, високосным. Правила определения високос- ных годов приведены в упражнениях главы 8. 2. Напишите команду if для проверки переменной, содержащей це- лое число, на четность. 3. Напишите команду if . Найдите блок с отступом и проверьте, какие символы использует ваш редактор при создании отступов — та- буляции или пробелы. Если отступы создаются символами табу- ляции, настройте свой редактор, чтобы он использовал пробелы. В некоторых редакторах табуляции отображаются иначе; если в ва- шем редакторе они отображаются одинаково, для проверки мож- но подвести курсор к отступу. Если курсор переместится сразу на 4 или 8 символов, значит, редактор вставил символ табуляции. 14 Контейнеры: списки, кортежи и множества Многие типы, рассматривавшиеся до настоящего момента, были ска- лярными величинами, содержащими одно значение. Целые числа, числа с плавающей точкой и логические значения — все это скалярные зна- чения. Контейнеры способны содержать не один, а несколько объектов (ска- лярные типы и даже другие контейнеры). В этой главе рассматриваются некоторые из таких типов — списки, кортежи и множества. 14.1. Списки Списки, как следует из самого названия, используются для хранения списков объектов. В Python список может содержать элементы про- извольного типа, в том числе и элементы разных типов. Впрочем, на практике в списках чаще хранятся элементы только одного типа. Список также можно представить себе как упорядоченную последовательность элементов. Списки относятся к изменяемым типам; это означает, что вы можете добавлять, удалять и изменять их содержимое без создания нового объекта. Существует два способа создания пустых списков; вызо- вом класса list и с использованием синтаксиса литералов в квадратных скобках — [ ] : >>> names = list() >>> other_names = [] 114 Глава 14. Контейнеры: списки, кортежи и множества Чтобы список при создании уже был заполнен, перечислите нужные значения в квадратных скобках с использованием синтаксиса литералов: >>> other_names = ['Fred', 'Charles'] ПРИМЕЧАНИЕ Класс list также может использоваться для создания заранее заполненных списков, но синтаксис получается довольно громоздким, потому что ему должен передаваться список: >>> other_names = list(['Fred', 'Charles']) Обычно этот класс используется для объединения других типов последо- вательностей в списки. Например, строка является последовательностью символов. Если передать строку при вызове list , вы получите список от- дельных символов: >>> list('Matt') ['M', 'a', 't', 't'] У списков, как и у других типов, имеются методы, которые можно для них вызывать (чтобы просмотреть полный перечень методов, исполь- зуйте вызов dir([]) ). Например, добавление элементов в конец списка осуществляется методом .append : >>> names.append('Matt') >>> names.append('Fred') >>> print(names) ['Matt', 'Fred'] Помните, что списки являются изменяемыми. Python не возвращает новый список при присоединении элементов. Обратите внимание: вы- зов .append не возвращает список (REPL ничего не выводит). Вместо этого возвращается None , а список обновляется на месте. В языке Python функция или метод по умолчанию возвращает None . Невозможно создать метод, который ничего не возвращает. |