Программирование на Python 3. Руководство издательство СимволПлюс
Скачать 3.74 Mb.
|
36 Глава 1. Быстрое введение в процедурное программирование использовать в том же духе. Однако язык Python дает точное опреде ление последовательностей и какие особенности должны ими поддер живаться, точно так же он точно определяет, какие особенности долж ны поддерживаться объектами, имеющими размер, и так далее для других категорий, которым могут принадлежать типы данных, но об этом будет рассказываться в главе 8. Списки, кортежи и другие типы коллекций, встроенные в язык Py thon, описываются в главе 3. Составляющая №4: логические операции Одна из фундаментальных особенностей любого языка программиро вания заключается в поддержке логических операций. Язык Python предоставляет четыре набора логических операций, и здесь мы рас смотрим основные принципы их использования. Оператор идентичности Поскольку все переменные в языке Python фактически являются ссылками, иногда возникает необходимость определить, не ссылаются ли две или более ссылок на один и тот же объект. Оператор is – это двухместный оператор, который возвращает True, если ссылка слева указывает на тот же самый объект, что и ссылка справа. Ниже приво дятся несколько примеров: >>> a = ["Retention", 3, None] >>> b = ["Retention", 3, None] >>> a is b False >>> b = a >>> a is b True Обратите внимание, что обычно не имеет смысла использовать опера тор is для сравнения типов данных int, str и некоторых других, так как обычно в этом случае бывает необходимо сравнить их значения. Фактически результаты сравнения данных с помощью оператора is могут приводить в замешательство, как это видно из предыдущего примера, где a и b первоначально имеют одинаковые значениясписки, однако сами списки хранятся в виде отдельных объектов типа list, и поэтому в первом случае оператор is вернул False. Одно из преимуществ операции проверки идентичности заключается в высокой скорости ее выполнения. Это обусловлено тем, что сравни ваются ссылки на объекты, а не сами объекты. Оператор is сравнивает только адреса памяти, в которых располагаются объекты – если адре са равны, следовательно, ссылки указывают на один и тот же объект. «Золотой запас» Python 37 Чаще всего оператор is используется для сравнения элемента данных со встроенным пустым объектом None, который часто применяется, чтобы показать, что значение «неизвестно» или «не существует»: >>> a = "Something" >>> b = None >>> a is not None, b is None (True, True) Для выполнения проверки на неидентичность, используется оператор is not Назначение оператора проверки идентичности состоит в том, чтобы узнать, ссылаются ли две ссылки на один и тот же объект, или прове рить, не ссылается ли ссылка на объект None. Если требуется сравнить значения объектов, мы должны использовать операторы сравнения. Операторы сравнения Язык Python предоставляет стандартный набор двухместных операто ров сравнения с предсказуемой семантикой: < меньше чем, <= меньше либо равно, == равно, != не равно, >= больше либо равно и > больше чем. Эти операторы сравнивают значения объектов, то есть объекты, на ко торые указывают ссылки, участвующие в сравнении. Ниже приводят ся примеры, набранные в командной оболочке Python: >>> a = 2 >>> b = 6 >>> a == b False >>> a < b True >>> a <= b, a != b, a >= b, a > b (True, True, False, False) Для целых чисел они действуют, как и следовало ожидать. Точно так же корректно выполняется сравнение строк: >>> a = "many paths" >>> b = "many paths" >>> a is b False >>> a == b True Хотя a и b ссылаются на разные объекты (с различными идентификаторами), тем не менее они имеют одинаковые значения, поэтому результат сравнения говорит о том, что они равны. Однако не следует забывать, что в языке Python для представления строк используется кодиров ка Юникод, поэтому сравнение строк, содержащих сим Сравнение строк, стр. 88 38 Глава 1. Быстрое введение в процедурное программирование волы, не входящие в множество ASCIIсимволов, может оказаться де лом более сложным, чем кажется на первый взгляд – подробнее эта проблема будет рассматриваться в главе 2. Одна из интересных особенностей операторов сравнения в языке Python заключается в том, что они могут объединяться в цепочки. Например: >>> a = 9 >>> 0 <= a <= 10 True Это отличный способ убедиться, что некоторый элемент данных нахо дится в пределах диапазона, вместо того чтобы выполнять два отдель ных сравнения, результаты которых объединяются логическим опера тором and, как это принято во многих других языках программирова ния. Кроме того, у этого подхода имеется дополнительное преимуще ство, так как оценка значения элемента данных производится только один раз (поскольку в выражении он появляется всего один раз), что может иметь большое значение, особенно когда вычисление значения элемента данных является достаточно дорогостоящей операцией или когда обращение к элементу данных имеет побочные эффекты. Благодаря «строгости» механизма динамического контроля типов в языке Python попытка сравнения несовместимых значений вызыва ет исключение. Например: >>> "three" < 4 Traceback (most recent call last): (Трассировочная информация (самый последний вызов внизу) TypeError: unorderable types: str() < int() (TypeError: несопоставимые типы: str() < int()) В случае, когда возбуждается необрабатываемое исключение, интер претатор Python выводит диагностическую информацию и текст сооб щения об ошибке. Для простоты мы опустили диагностическую ин формацию здесь, заменив ее многоточием. 1 То же самое исключение TypeError возникнет, если записать "3" < 4, потому что Python никогда не пытается строить предположения о наших намерениях – правиль ный подход заключается в том, чтобы выполнить явное преобразова ние, например: int("3") < 4, или использовать сопоставимые типы, то есть оба значения должны быть либо целыми числами, либо строками. 1 Диагностическая информация (иногда называется обратной трассировкой (backtrace)) – это список всех вызовов функций, которые были произведе ны к моменту возбуждения необрабатываемого исключения, в обратном порядке. «Золотой запас» Python 39 Язык Python позволяет нам легко создавать свои собст венные, легко интегрируемые типы данных, благодаря чему, например, мы могли бы создать свой собственный числовой тип, который смог бы участвовать в операциях сравнения со встроенным типом int и другими встроен ными или нашими собственными числовыми типами, но не со строками или другими нечисловыми типами. Оператор членства Для типов данных, являющихся последовательностями или коллек циями, таких как строки, списки и кортежи, мы можем выполнить проверку членства с помощью оператора in, а проверку обратного ут верждения – с помощью оператора not in. Например: >>> p = (4, "frog", 9, 33, 9, 2) >>> 2 in p True >>> "dog" not in p True Применительно к спискам и кортежам оператор in выполняет линей ный поиск, который может оказаться очень медленным для огромных коллекций (десятки тысяч элементов или больше). С другой стороны, со словарями или со множествами оператор in работает очень быстро – оба этих типа данных рассматриваются в главе 3. Ниже демонстриру ется, как оператор in может использоваться со строками: >>> phrase = "Peace is no longer permitted during Winterval" >>> "v" in phrase True >>> "ring" in phrase True Применительно к строкам оператор in удобно использовать для провер ки вхождения в строку подстроки произвольной длины. (Как отмеча лось ранее, символ – это всего лишь строка, имеющая длину, равную 1.) Логические операторы Язык Python предоставляет три логических оператора: and, or и not. Операторы and и or вычисляются по короткой схеме и возвращают опе ранд, определяющий результат, – они не возвращают значение типа Boolean (если операнды не являются значениями типа Boolean). Взгля ните, что это означает на практике: >>> five = 5 >>> two = 2 >>> zero = 0 >>> five and two 2 Альтерна тивный тип FuzzyBool , стр. 300 40 Глава 1. Быстрое введение в процедурное программирование >>> two and five 5 >>> five and zero 0 Если выражение участвует в логическом контексте, результат оцени вается как значение типа Boolean, поэтому предыдущие выражения могли бы рассматриваться, как имеющие значения True, True и False, например, в контексте инструкции if. >>> nought = 0 >>> five or two 5 >>> two or five 2 >>> zero or five 5 >>> zero or nought 0 Оператор or напоминает оператор and – здесь в булевом контексте были бы получены значения True, True, True и False. Унарный оператор not оценивает свой операнд в булевом контексте и всегда возвращает значение типа Boolean, поэтому, продолжая пре дыдущий пример, выражение not (zero or nought) вернет значение True , а выражение not two – False. Составляющая №5: инструкции управления потоком выполнения Мы упоминали ранее, что все инструкции, встречающиеся в файле с расширением .py, выполняются по очереди, строка за строкой. Поря док движения потока управления может изменяться вызовами функ ций и методов или структурами управления, такими как условные операторы или операторы циклов. Поток управления также отклоня ется, когда возбуждаются исключения. В этом подразделе мы рассмотрим условный оператор if, а также опе раторы циклов while и for, отложив рассмотрение функций до раздела с описанием составляющей №8, а рассмотрение методов – до главы 6. Мы также коротко коснемся вопросов обработки исключений, кото рые подробнее будут обсуждаться в главе 4. Но для начала мы опреде лим пару терминов. Булево (Boolean) выражение – это выражение, которое может оцени ваться как булево (Boolean) значение (True или False). В языке Python выражение оценивается как False, если это предопределенная кон станта False, специальный объект None, пустая последовательность или коллекция (например, пустая строка, список или кортеж), или число вой элемент данных со значением 0. Все остальное оценивается как «Золотой запас» Python 41 True . При создании своих собственных типов данных (как будет рас сказываться в главе 6) мы сами сможем определять, какое значение возвращать в булевом контексте. В языке Python используется понятие блока программного кода – suite 1 , представляющего собой последовательность одной или более инструкций. Так как некоторые синтаксические конструкции языка Python требуют наличия блока кода, Python предоставляет ключевое слово pass, которое представляет собой инструкцию, не делающую ровным счетом ничего, и которая может использоваться везде, где тре буется блок кода (или когда мы хотим указать на наличие особого слу чая), но никаких действий выполнять не требуется. Инструкция if В общем случае инструкция if имеет следующий синтаксис: 2 if boolean_expression1: suite1 elif boolean_expression2: suite2 elif boolean_expressionN: suiteN else: else_suite В инструкции может быть ноль или более предложений elif, а заклю чительное предложение else является необязательным. Если необхо димо принять в учет какойто особый случай, не требующий обработ ки, мы можем использовать ключевое слово pass в качестве блока кода соответствующей ветки. Первое, что бросается в глаза программистам, использовавшим язык C++ или Java, – это отсутствие круглых и фигурных скобок. Еще одна особенность, на которую следует обратить внимание, – это двоеточие, которое является частью синтаксиса и о котором легко забыть на пер вых порах. Двоеточия используются с предложениями else, elif и прак тически везде, где вслед за предложением должен следовать блок кода. В отличие от большинства других языков программирования, отсту пы в языке Python используются для обозначения блочной структу ры. Некоторым программистам не нравится эта черта, особенно до то го, пока они не испытают ее на практике, а некоторые весьма эмоцио нально высказываются по этому поводу. Однако чтобы привыкнуть к ней, требуется всего несколько дней, а спустя несколько недель или 1 Во многих других языках программирования такой блок программного ко да называется составным оператором. – Прим. перев. 2 В этой книге многоточия (…) приводятся взамен строк, которые не пока заны. 42 Глава 1. Быстрое введение в процедурное программирование месяцев программный код без скобок начинает восприниматься как более удобочитаемый и менее захламленный, чем программный код со скобками. Так как блоки кода оформляются посредством отступов, естественно, возникает вопрос, какие отступы использовать. Руководства по оформ лению программного кода на языке Python рекомендуют использовать четыре пробела на каждый уровень и использовать только пробелы (а не символы табуляции). Большинство современных текстовых ре дакторов могут быть настроены на автоматическую обработку отступов (редактор среды IDLE, конечно же, предусматривает такую возмож ность, как и большинство других редакторов, поддерживающих язык программирования Python). Интерпретатор Python прекрасно будет справляться с любыми отступами, содержащими любое число пробе лов или символов табуляции или смесь из тех и других – главное, что бы оформление отступов выполнялось непротиворечивым образом. В этой книге мы следуем официальным рекомендациям Python. Ниже приводится пример простой инструкции if: if x: print("x is nonzero") В данном случае, если условное выражение (x) оценивается как True, блок кода (вызов функции print()) будет выполнен. if lines < 1000: print("small") elif lines < 10000: print("medium") else: print("large") Это немного более сложная инструкция if, которая выводит оценку, описывающую значение переменной lines. Инструкция while Инструкция while используется для выполнения своего блока кода ноль или более раз, причем число раз зависит от булева выражения в инструкции while. Ниже приводится синтаксис этой инструкции: while boolean_expression: suite В действительности полный синтаксис цикла while – более сложный, чем показано здесь, так как дополнительно поддерживаются инструк ции break и continue, а также предложение else, о чем подробно будет рассказываться в главе 4. Инструкция break передает управление за пределы самого внутреннего цикла, в котором она встречается, то есть прерывает выполнение цикла. Инструкция continue передает управле ние в начало цикла. Как правило, инструкции break и continue исполь «Золотой запас» Python 43 зуются внутри инструкций if, чтобы в зависимости от складываю щихся условий изменять поведение цикла. while True: item = get_next_item() if not item: break process_item(item) Этот цикл while имеет вполне типичную структуру и выполняется до тех пор, пока не будут исчерпаны элементы для обработки. (Предпола гается, что функции get_next_item() и process_item() – это наши собст венные функции, определенные гдето в другом месте.) В этом приме ре блок кода инструкции while содержит инструкцию if, имеющую, как ей и положено, свой собственный блок кода – в данном случае со стоящий из единственной инструкции break. Инструкция for … in Инструкция цикла for в языке Python повторно использует ключевое слово in (которое в других контекстах играет роль оператора проверки членства) и имеет следующий синтаксис: for variable in iterable: suite Точно так же, как и в случае с циклом while, инструкция for поддержи вает инструкции break и continue, а также необязательное предложение else . Переменная variable поочередно указывает на каждый объект в объекте iterable. В качестве iterable может использоваться любой тип данных, допускающий выполнение итераций по нему, включая строки (где итерации выполняются по символам строки), списки, кор тежи и другие типы коллекций языка Python. for country in ["Denmark", "Finland", "Norway", "Sweden"]: print(country) Здесь мы использовали весьма упрощенный подход к выводу списка стран. На практике то же самое обычно делается с помощью перемен ных: countries = ["Denmark", "Finland", "Norway", "Sweden"] for country in countries: print(country) На самом деле весь список (или кортеж) можно вывести единственным вызовом функции print(), например, print(countries) , но часто предпочтительнее выводить содержимое коллекций в цикле for (или в генераторах списков, о которых будет рассказываться позже), чтобы иметь полный контроль над форматированием. Генераторы списков, стр. 142 44 Глава 1. Быстрое введение в процедурное программирование for letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": if letter in "AEIOU": print(letter, "is a vowel") else: print(letter, "is a consonant") В первой строке этого фрагмента мы использовали ключевое слово in, как часть инструкции for, и переменную letter, последовательно при нимающую значения "A", "B" и так далее до "Z" на каждом проходе цикла. Во второй строке мы снова использовали ключевое слово in, но на этот раз в качестве оператора проверки членства. Обратите также внимание на то, что в этом примере присутствуют вложенные блоки кода. Блок кода цикла for представлен инструкцией if ...else, а обе ветки – и if, и else – имеют свои собственные блоки кода. Основы обработки исключений Многие функции и методы в языке Python в случае появления ошибок или наступления других важных событий возбуждают исключения. Исключение – это объект, такой же как любые другие объекты в язы ке Python, который при преобразовании в строку (то есть при выводе на экран) воспроизводится как строка с текстом сообщения. Ниже по казана простейшая форма обработки исключений: try: try_suite except exception1 as variable1: exception_suite1 … except exceptionN as variableN: exception_suiteN Обратите внимание на то, что часть as variable является необязатель ной – нас может волновать только сам факт возникновения исключе ния, а текст сообщения может быть для нас неинтересен. Полный синтаксис имеет более сложный вид, например, каждое пред ложение except может обрабатывать несколько исключений, а кроме того, можно использовать необязательное предложение else. Обо всем этом подробно рассказывается в главе 4. Эта конструкция работает следующим образом. Если инструкции в блоке кода try выполняются без ошибок, блоки except просто пропус каются. Если в блоке try будет возбуждено исключение, управление немедленно будет передано блоку первого соответствующего предло жения except – то есть любые инструкции в блоке try, расположенные ниже инструкции, вызвавшей исключение, выполняться не будут. В случае исключения и если указана часть as variable, внутри блока обработки исключения переменная variable будет ссылаться на объект исключения. |