Математический анализ. 3е издание
Скачать 4.86 Mb.
|
import sys # Вывод более сложным способом >>> sys.stdout.write('hello world\n') hello world В этом фрагменте явно вызывается метод write объекта sys.stdout – ат рибут, предустановленный интерпретатором Python во время откры тия файла, связанного с потоком вывода. Инструкция print скрывает большую часть этих подробностей, предоставляя простой инструмент для решения простых задач вывода. Перенаправление потока вывода Итак, почему я показал пока единственный способ вывода? Как ока зывается, объект sys.stdout обеспечивает возможность вывода, экви валентную базовой методике, используемой в языке Python. Вообще говоря, инструкция print и объект sys.stdout связаны между собой следующим образом. Следующая инструкция: print X Инструкция print 309 является эквивалентом более длинной: import sys sys.stdout.write(str(X) + '\n') которая вручную выполняет преобразование объекта в строку с помо щью функции str, добавляет символ новой строки с помощью операто ра + и вызывает метод write потока вывода. Более длинная форма сама по себе не так удобна в использовании. Однако полезно знать, что она является точным эквивалентом инструкции print, потому что сущест вует возможность перенаправить sys.stdout в место, отличное от стан дартного потока вывода. Другими словами, эта эквивалентность обеспе чивает возможность заставить инструкцию print выводить текст в дру гое место. Например: import sys sys.stdout = open('log.txt', 'a') # Перенаправить вывод в файл print x, y, x # Текст появится в файле log.txt Здесь мы вручную перенаправили объект sys.stdout в файл, открытый вручную в режиме добавления. После этого все инструкции print в про грамме будут выводить текст в конец файла log.txt, а не в стандартный поток вывода. Инструкции print благополучно продолжают вызывать метод write объекта sys.stdout независимо от того, куда он ссылается. Поскольку в каждом процессе существует всего один модуль sys, пере направление sys.stdout таким способом будет воздействовать на все инструкции print в программе. Фактически, как будет говориться в ближайшей врезке, описываю щей инструкцию print и объект stdout, существует возможность пере направить sys.stdout в объект, который даже не является файлом, при условии, что он соответствует ожидаемому протоколу (метод write), – в этом случае объект может быть классом, который может обрабаты вать и перенаправлять выводимый текст произвольным образом. Этот прием с перенаправлением потока вывода в первую очередь мо жет оказаться полезен в программах, изначально рассчитанных на ис пользование инструкции print. Если известно, что весь вывод должен отправляться в файл, вы всегда сможете организовать вызов методов записи в файл. При перенаправлении потока вывода в программах, основанных на использовании инструкции print, настройка объекта sys.stdout обеспечивает удобную альтернативу изменению поведения всех инструкций print или применению перенаправления средствами командной оболочки системы. Расширение print >> file Прием перенаправления вывода текста за счет назначения файла в объ екте sys.stdout очень часто используется на практике. Однако в про граммном коде предыдущего раздела имеется одна потенциальная 310 Глава 11. Присваивание, выражения и print проблема – отсутствует прямой способ восстановления первоначально го потока вывода, если вдруг после вывода данных в файл потребуется вернуться обратно к выводу на экран. Но поскольку sys.stdout является обычным объектом, вы всегда можете в случае необходимости сохра нить его и восстановить позднее: 1 >>> import sys >>> temp = sys.stdout # Сохранить для последующего восстановления >>> sys.stdout = open('log.txt', 'a') # Перенаправить вывод в файл >>> print 'spam' # Вывести в файл, а не на экран >>> print 1, 2, 3 >>> sys.stdout.close() # Вытолкнуть буферы на диск >>> sys.stdout = temp # Восстановить первоначальный поток >>> print 'back here' # Вывести на экран back here >>> print open('log.txt').read() # Результаты более ранних обращений spam # к инструкции print 1 2 3 Потребность в таком перенаправлении возникает на удивление часто, а ручное сохранение и восстановление оригинального потока вывода – процедура достаточно сложная, что привело к появлению расширения для инструкции print, которое делает такое перенаправление ненуж ным. Когда инструкция print начинается с символов >>, вслед за кото рыми указывается объект файла (или другой объект) для вывода, та кая инструкция посылает текст методу write указанного объекта, но при этом не происходит перенаправления объекта sys.stdout. Посколь ку в этом случае перенаправление носит временный характер, обыч ные инструкции print продолжают выводить текст в оригинальный поток вывода: log = open('log.txt', 'a') print >> log, x, y, z # Вывести в объект, напоминающий файл print a, b, c # Вывести в оригинальный поток вывода Расширение >> удобно использовать, когда в одной и той же программе необходимо организовать вывод и в файл, и в стандартный поток выво да. Однако, если вы собираетесь использовать эту форму инструкции, вам потребуется создать объектфайл (или объект, который имеет ме тод write, как и объект файла) и передавать инструкции этот объект, а не строку с именем файла: 1 Можно также использовать относительно новый атрибут __stdout__ объек та sys.stdout, который ссылается на первоначальное значение sys.stdout, имевшееся на момент запуска программы. Но вам и в этом случае необхо димо вручную восстановить sys.stdout в первоначальное значение __stdout__ , чтобы вернуться к оригинальному потоку вывода. За дополни тельными подробностями обращайтесь к описанию модуля sys в руково дстве по стандартной библиотеке. Инструкция print 311 >>> log = open('log.txt', 'w') >>> print >> log, 1, 2, 3 >>> print >> log, 4, 5, 6 >>> log.close() >>> print 7, 8, 9 7 8 9 >>> print open('log.txt').read() 1 2 3 4 5 6 Эта расширенная форма инструкции print нередко используется для вывода сообщений об ошибках в стандартный поток ошибок, sys.stderr. Вы можете либо использовать его метод write и форматировать выводи мые строки вручную, либо использовать синтаксис перенаправления: >>> import sys >>> sys.stderr.write(('Bad!' * 8) + '\n') Bad!Bad!Bad!Bad!Bad!Bad!Bad!Bad! >>> print >> sys.stderr, 'Bad!' * 8 Bad!Bad!Bad!Bad!Bad!Bad!Bad!Bad! Придется держать в уме: print и stdout Эквивалентность инструкции print и метода write объекта sys.stdout имеет большое значение. Она позволяет перенапра вить объект sys.stdout в определяемый пользователем объект, который поддерживает те же методы, что и файлы (например, write ). Так как инструкция print всего лишь передает текст мето ду sys.stdout.write, вы можете перехватывать выводимый текст, перенаправив sys.stdout в объект, обладающий методом write для обработки текста. Например, можно отправить текст в окно графического интер фейса или отправить его в несколько мест, определив объект с ме тодом write, который выполнит все необходимые действия. При мер использования такой возможности вы увидите далее в кни ге, когда мы будем изучать классы, но в общих чертах это выгля дит примерно так: class FileFaker: def write(self, string): # Выполнить какиелибо действия со строкой import sys sys.stdout = FileFaker() print someObjects # Передает строку методу write класса 312 Глава 11. Присваивание, выражения и print Предполагается, что в Python 3.0 инструкция print превратится во встроенную функцию с эквивалентными возможностями, но с несколько иным синтаксисом. Выходной файл и необходимость вывода символа конца строки будут определяться аргументами с зарезервированными именами. Например, инструкция print x, y превратится в вызов print(x, y), а инструкция print >> f, x – в вызов print(x, file=f, end=''). Но все это будет в будущем, поэтому за дополнительной информа цией обращайтесь к примечаниям к выпуску 3.0. В настоящее время предложено включить в версию 3.0 сценарий (с рабочим названием «2to3»), который кроме всего прочего будет выпол нять преобразование инструкций print в существующем про граммном коде в вызовы функции print. Он должен помочь вам в переходе с версии 2.x на версию 3.x (как и эта книга!). В заключение В этой главе мы начали детальный обзор инструкций языка Python, исследовав инструкции присваивания, выражения и print. Несмотря Этот прием возможен благодаря тому, что инструкция print яв ляется тем, что в следующей части книги мы назовем полиморф+ ной операцией, – она не интересуется тем, что из себя представ ляет объект sys.stdout, ей нужен всего лишь метод (т. е. интер фейс) с именем write. В последних версиях Python перенаправле ние в объекты реализовано еще проще, с помощью расширенной формы >> инструкции print, благодаря чему нам не требуется яв но перенаправлять объект sys.stdout: myobj = FileFaker() # Перенаправление вывода для одной инструкции print >> myobj, someObjects # Не влияет на объект sys.stdout Встроенная функция raw_input() в языке Python читает данные из файла sys.stdin, поэтому существует возможность перенапра вить ввод аналогичным образом, используя классы, реализую щие метод read. Смотрите примеры использования функции raw_input и цикла while, которые приводятся в главе 10, чтобы получить дополнительные начальные сведения по этой теме. Обратите внимание: вывод текста осуществляется в поток stdout, что обеспечивает возможность вывода документов HTML в CGI сценариях. Кроме того, это позволяет выполнить перенаправле ние ввода и вывода для сценария на языке Python обычными средствами командной строки операционной системы: python script.py < inputfile > outputfile python script.py | filterProgram Закрепление пройденного 313 на всю простоту использования этих инструкций, у них имеются аль тернативные формы, которые являются необязательными, но порой достаточно удобными в применении. Комбинированные инструкции присваивания и форма инструкции print с перенаправлением, напри мер, позволяют уменьшить объем программного кода. Кроме того, мы изучили синтаксис имен переменных, приемы перенаправления пото ков и различные часто встречающиеся ошибки, которых следует избе гать, такие как обратное присваивание переменной значения, возвра щаемого методом append. В следующей главе мы продолжим наше знакомство с инструкциями, подробно рассмотрев инструкцию if – основную инструкцию органи зации выбора в языке Python. В этой главе мы еще раз вернемся к син таксической модели языка и рассмотрим поведение логических выра жений. Но прежде чем двинуться дальше, проверьте знания, получен ные здесь, с помощью контрольных вопросов. Закрепление пройденного Контрольные вопросы 1. Назовите три способа, с помощью которых можно присвоить одно и то же значение трем переменным. 2. Что требуется держать в уме, когда трем переменным присваивает ся один и тот же изменяемый объект? 3. В чем заключается ошибка в инструкции L = L.sort()? 4. Как с помощью инструкции print вывести текст во внешний файл? Ответы 1. Можно выполнить групповое присваивание (A = B = C = 0), при сваивание последовательности (A, B, C = 0, 0, 0) или несколько ин струкций присваивания в отдельных строках (A = 0, B = 0, C = 0). И последний способ, как было показано в главе 10, заключается в том, чтобы объединить инструкции в одной строке, разделив их точкой с запятой (A = 0; B = 0; C = 0). 2. Если выполнить присваивание следующим образом: A = B = C = [] то все три имени будут ссылаться на один и тот же объект, поэтому непосредственное изменение объекта с помощью одной переменной (например, A.append(99)) отразится на других. Это справедливо только для изменений, производимых непосредственно в изменяе мых объектах, таких как списки и словари. Для неизменяемых объектов, таких как числа и строки, эта проблема не проявляется. 3. Метод списков sort, как и метод append, выполняет изменения непо средственно в объекте и возвращает значение None, а не измененный 314 Глава 11. Присваивание, выражения и print список. Обратное присваивание переменной L приведет к тому, что в нее запишется значение None, а не отсортированный список. Как будет показано далее в этой части книги, недавно в языке появи лась новая функция sorted, которая выполняет сортировку любых последовательностей и возвращает новый список с результатами сортировки. Поскольку в этом случае изменения производятся не в самом объекте, есть смысл сохранить возвращаемое значение. 4. Можно вручную перенаправить объект sys.stdout, открыв файл пе ред вызовом инструкции print, или использовать расширенную форму инструкции print >> file для вывода в файл единственной инструкцией. Можно также перенаправить весь выводимый про граммой текст в файл с помощью синтаксических конструкций сис темной командной оболочки, но этот вариант к языку Python ника кого отношения не имеет. 12 Условная инструкция if Эта глава представляет условную инструкцию if, которая является ос новной инструкцией, используемой для выбора среди альтернативных операций на основе результатов проверки. Поскольку в нашем обзоре это первая составная инструкция – инструкция, встроенная в другую инструкцию, – мы заодно более подробно рассмотрим общие концеп ции, на которых покоится синтаксическая модель инструкций в язы ке Python. А так как условная инструкция вводит понятие проверки, мы также будем иметь дело с логическими выражениями и остановим ся на некоторых деталях относительно проверок истинности вообще. Условные инструкции if Если говорить простым языком, в Python инструкция if выбирает, ка кое действие следует выполнить. Это основной инструмент выбора в Python, который отражает большую часть логики программы на язы ке Python. Кроме того, это наша первая составная инструкция. Как и все составные инструкции языка Python, инструкция if может со держать другие инструкции, в том числе другие условные инструкции if . Фактически Python позволяет комбинировать инструкции в про граммные последовательности (чтобы они выполнялись одна за дру гой) и в произвольно вложенные конструкции (которые выполняются только при соблюдении определенных условий). Общая форма Условная инструкция if в языке Python – это типичная условная инст рукция, которая присутствует в большинстве процедурных языков программирования. Синтаксически сначала записывается часть if с ус ловным выражением, далее могут следовать одна или более необяза тельных частей elif («else if») с условными выражениями и, наконец, 316 Глава 12. Условная инструкция if необязательная часть else. Условные выражения и часть else имеют ас социированные с ними блоки вложенных инструкций, с отступом отно сительно основной инструкции. Во время выполнения условной инст рукции if интерпретатор выполняет блок инструкций, ассоциирован ный с первым условным выражением, только если оно возвращает ис тину, в противном случае выполняется блок инструкций else. Общая форма записи условной инструкции if выглядит следующим образом: if elif else: # Необязательный блок else Простые примеры C целью демонстрации инструкции if в действии рассмотрим несколь ко простых примеров. Все части этой инструкции, за исключением ос новной части if с условным выражением и связанных с ней инструк ций, являются необязательными. В простейшем случае остальные час ти инструкции опущены: >>> if 1: ... print 'true' true Обратите внимание, что приглашение к вводу изменяется на ... для строк продолжения в базовом интерфейсе командной строки, исполь зуемом здесь (в IDLE текстовый курсор просто перемещается на сле дующую строку уже с отступом, а нажатие на клавишу Backspace воз вращает на строку вверх). Ввод пустой строки завершает инструкцию и приводит к ее выполнению. Вспомните, что число 1 является логиче ской истиной, поэтому данная проверка всегда будет успешной. Чтобы обработать ложный результат, добавьте часть else: >>> if not 1: ... print 'true' ... else: ... print 'false' false Множественное ветвление Теперь рассмотрим пример более сложной условной инструкции if, в которой присутствуют все необязательные части: >>> x = 'killer rabbit' >>> if x == 'roger': ... print "how's jessica?" Условные инструкции if 317 ... elif x == 'bugs': ... print "what's up doc?" ... else: ... print 'Run away! Run away!' Run away! Run away! Эта многострочная инструкция простирается от строки if до конца блока else. При выполнении этой инструкции интерпретатор выпол нит вложенные инструкции после той проверки, которая даст в ре зультате истину, или блок else, если все проверки дадут ложный ре зультат (в этом примере так и происходит). На практике обе части elif и else могут быть опущены и в каждой части может иметься более од ной вложенной инструкции. Обратите внимание, что связь слов if, elif и else определена тем, что они находятся на одной вертикальной линии, с одним и тем же отступом. Если вы знакомы с такими языками, как C или Pascal, вам будет инте ресно узнать, что в языке Python отсутствует инструкция switch или case , которая позволяет выбирать производимое действие на основе значения переменной. Вместо этого множественное ветвление оформ ляется либо в виде последовательности проверок if/elif, как в преды дущем примере, либо индексированием словарей, либо поиском в спи сках. Поскольку словари и списки могут создаваться во время выпол нения, они иногда способны обеспечить более высокую гибкость, чем жестко заданная логика инструкции if: >>> |