справочник по Python. мм isbn 9785932861578 9 785932 861578
Скачать 4.21 Mb.
|
Hello WorldClick here. ‘’’ Строки хранятся как последовательности символов, доступ к которым можно получить с помощью целочисленного индекса, начиная с нуля. Что- бы извлечь из строки единственный символ, можно использовать оператор индексирования s[i], например: Строки 31 a = “Привет, Мир” b = a[4] # b = ‘е’ Чтобы извлечь подстроку, можно использовать оператор сечения s[i:j]. Он извлечет из строки s все символы с порядковыми номерами k в диапазоне i <= k < j . Если какой-либо из индексов опущен, предполагается, что он со- ответствует началу или концу строки соответственно: c = a[:6] # c = “Привет” d = a[8:] # d = “Мир” e = a[3:9] # e = “вет, М” Конкатенация строк выполняется с помощью оператора сложения (+): g = a + “ Это проверка” Интерпретатор Python никогда не интерпретирует строку как число, даже если она содержит только цифровые символы (как это делается в других языках, таких как Perl или PHP). Например, оператор + всегда выполняет конкатенацию строк: x = “37” y = “42” z = x + y # z = “3742” (конкатенация строк) Чтобы выполнить арифметическую операцию над значениями, хранящи- мися в виде строк, необходимо сначала преобразовать строки в числовые значения с помощью функции int() или float(). Например: z = int(x) + int(y) # z = 79 (целочисленное сложение) Нестроковые значения можно преобразовать в строковое представление с помощью функции str(), repr() или format(). Например: s = “Значение переменной x: “ + str(x) s = “Значение переменной x: “ + repr(x) s = “Значение переменной x: “ + format(x,”4d”) Несмотря на то что обе функции str() и repr() воспроизводят строки, на самом деле возвращаемые ими результаты обычно немного отличаются. Функция str() воспроизводит результат, который дает применение ин- струкции print, тогда как функция repr() воспроизводит строку в том виде, в каком она обычно вводится в тексте программы для точного представле- ния значения объекта. Например: >>> x = 3.4 >>> str(x) ‘3.4’ >>> repr(x) ‘3.3999999999999999’ >>> Ошибка округления числа 3.4 в предыдущем примере не является ошиб- кой Python. Это следствие особенностей представления чисел с плавающей точкой двойной точности, которые не могут быть точно представлены в де- сятичном формате из-за аппаратных ограничений компьютера. 32 Глава 1. Вводное руководство Для преобразования значений в строку с возможностью форматирования используется функция format(). Например: >>> format(x,”0.5f”) ‘3.40000’ >>> Списки Списки – это последовательности произвольных объектов. Списки созда- ются посредством заключения элементов списка в квадратные скобки, как показано ниже: names = [ “Dave”, “Mark”, “Ann”, “Phil” ] Элементы списка индексируются целыми числами, первый элемент списка имеет индекс, равный нулю. Для доступа к отдельным элементам списка используется оператор индексирования: a = names[2] # Вернет третий элемент списка, “Ann” names[0] = “Jeff” # Запишет имя “Jeff” в первый элемент списка Для добавления новых элементов в конец списка используется метод ap- pend() : names.append(“Paula”) Для вставки элемента в середину списка используется метод insert(): names.insert(2, “Thomas”) С помощью оператора среза можно извлекать и изменять целые фрагменты списков: b = names[0:2] # Вернет [“Jeff”, “Mark”] c = names[2:] # Вернет [“Thomas”, “Ann”,“Phil”,“Paula”] names[1] = ‘Jeff’ # Во второй элемент запишет имя ‘Jeff’ names[0:2] = [‘Dave’,’Mark’,’Jeff’] # Заменит первые два элемента # списком справа. Оператор сложения (+) выполняет конкатенацию списков: a = [1,2,3] + [4,5] # Создаст список [1,2,3,4,5] Пустой список можно создать одним из двух способов: names = [] # Пустой список names = list() # Пустой список Список может содержать объекты любого типа, включая другие списки, как показано в следующем примере: a = [1,”Dave”,3.14, [“Mark”, 7, 9, [100,101]], 10] Доступ к элементам во вложенных списках осуществляется с применени- ем дополнительных операторов индексирования, как показано ниже: Кортежи 33 a[1] # Вернет “Dave” a[3][2] # Вернет 9 a[3][3][1] # Вернет 101 Программа в листинге 1.2 демонстрирует дополнительные особенности списков. Она читает список чисел из файла, имя которого указывается в виде аргумента командной строки, и выводит минимальное и макси- мальное значения. Листинг 1.2. Дополнительные особенности списков import sys # Загружает модуль sys if len(sys.argv) != 2 : # Проверка количества аргументов командной строки: print “Пожалуйста, укажите имя файла” raise SystemExit(1) f = open(sys.argv[1]) # Имя файла, полученное из командной строки lines = f.readlines() # Читает все строки из файла в список f.close() ёё # Преобразовать все значения из строк в числа с плавающей точкой fvalues = [float(line) for line in lines] ёё # Вывести минимальное и максимальное значения print “Минимальное значение: “, min(fvalues) print “Максимальное значение: “, max(fvalues) В первой строке этой программы с помощью инструкции import загружает- ся модуль sys из стандартной библиотеки Python. Этот модуль использует- Python. Этот модуль использует- . Этот модуль использует- ся для получения доступа к аргументам командной строки. Функции open() передается имя файла, которое было получено как аргу- мент командной строки и помещено в список sys.argv. Метод readlines() чи- тает все строки из файла и возвращает список строк. Выражение [float(line) for line in lines] создает новый список, выпол- няя обход всех строк и применяя функцию float() к каждой из них. Эта конструкция, чрезвычайно удобная для создания списков, называется ге- нератором списков . Поскольку строки из файла можно также читать с по- мощью цикла for, программу можно сократить, объединив чтение файла и преобразование значений в одну инструкцию, как показано ниже: fvalues = [float(line) for line in open(sys.argv[1])] После того как входные строки будут преобразованы в список, содержа- щий числа с плавающей точкой, с помощью встроенных функций min() и max() отыскиваются минимальное и максимальное значения. Кортежи Для создания простейших структур данных можно использовать корте- жи , которые позволяют упаковывать коллекции значений в единый объ- ект. Кортеж создается заключением группы значений в круглые скобки, например: stock = (‘GOOG’, 100, 490.10) 34 Глава 1. Вводное руководство address = (‘www.python.org’, 80) person = (first_name, last_name, phone) Интерпретатор Python часто распознает кортежи, даже если они не заклю- Python часто распознает кортежи, даже если они не заклю- часто распознает кортежи, даже если они не заклю- чены в круглые скобки: stock = ‘GOOG’, 100, 490.10 address = ‘www.python.org’,80 person = first_name, last_name, phone Для полноты можно отметить, что имеется возможность определять кор- тежи, содержащие 0 или 1 элемент, для чего используется специальный синтаксис: a = () # Кортеж с нулевым количеством элементов (пустой кортеж) b = (item,) # Кортеж с одним элементом (обратите внимание на запятую в конце) c = item, # Кортеж с одним элементом (обратите внимание на запятую в конце) Элементы кортежа могут извлекаться с помощью целочисленных индек- сов, как и в случае со списками. Однако более часто используется прием распаковывания кортежей во множество переменных, как показано ниже: name, shares, price = stock host, port = address first_name, last_name, phone = person Кортежи поддерживают практически те же операции, что и списки (такие как доступ к элементам по индексу, извлечение среза и конкатенация), тем не менее содержимое кортежа после его создания невозможно изменить (то есть нельзя изменить, удалить или добавить новый элемент в существую- щий кортеж). По этой причине кортеж лучше рассматривать как единый объект, состоящий из нескольких частей, а не как коллекцию отдельных объектов, в которую можно вставлять новые или удалять существующие элементы. Вследствие большого сходства кортежей и списков некоторые программи- сты склонны полностью игнорировать кортежи и использовать списки, по- тому что они выглядят более гибкими. Хотя в значительной степени это так и есть, тем не менее, если в программе создается множество небольших списков (когда каждый содержит не более десятка элементов), то они за- нимают больший объем памяти, по сравнению с кортежами. Это обуслов- лено тем, что для хранения списков выделяется немного больше памяти, чем требуется, – с целью оптимизировать скорость выполнения операций, реализующих добавление новых элементов. Так как кортежи доступны только для чтения, для их хранения используется меньше памяти, т. к. до- полнительное пространство не выделяется. Кортежи и списки часто используются совместно. Например, следующая программа демонстрирует, как можно организовать чтение данных из фай- ла с переменным количеством столбцов, где значения отделяются друг от друга запятыми: # Файл содержит строки вида “name,shares,price” filename = “portfolio.csv” portfolio = [] Множества 35 for line in open(filename): fields = line.split(“,”) # Преобразует строкувсписок name = fields[0] # Извлекает ипреобразуетотдельныезначенияполей shares = int(fields[1]) price = float(fields[2]) stock = (name,shares,price) # Создает кортеж(name,shares,price) portfolio.append(stock) # Добавляет всписокзаписей Строковый метод split() разбивает строку по указанному символу и соз- дает список значений. Структура данных portfolio, созданная этой про- граммой, имеет вид двухмерного массива строк и столбцов. Каждая строка представлена кортежем и может быть извлечена, как показано ниже: >>> portfolio[0] (‘GOOG’, 100, 490.10) >>> portfolio[1] (‘MSFT’, 50, 54.23) >>> Отдельные значения могут извлекаться следующим способом: >>> portfolio[1][1] 50 >>> portfolio[1][2] 54.23 >>> Ниже приводится простейший способ реализовать обход всех записей и распаковать значения полей в набор переменных: total = 0.0 for name, shares, price in portfolio: total += shares * price Множества Множества используются для хранения неупорядоченных коллекций объектов. Создаются множества с помощью функции set(), которой пере- даются последовательности элементов, как показано ниже: s = set([3,5,9,10]) # Создаст множество чисел t = set(“Hello”) # Создаст множество уникальных символов В отличие от кортежей, множества являются неупорядоченными коллек- циями и не предусматривают возможность доступа к элементам по число- вому индексу. Более того, элементы множества никогда не повторяются. Например, если поближе рассмотреть значения, полученные в предыду- щем примере, можно заметить следующее: >>> t set([‘H’, ‘e’, ‘l’, ‘o’]) Обратите внимание, что в множестве присутствует только один символ ‘l’. 36 Глава 1. Вводное руководство М ножества поддерживают стандартные операции над коллекциями, включая объединение, пересечение, разность и симметричную разность. Например: a = t | s # Объединение t и s b = t & s # Пересечение t и s c = t – s # Разность (элементы, присутствующие в t, но отсутствующие в s) d = t ^ s # Симметричная разность (элементы, присутствующие в t или в s, # но не в двух множествах сразу) С помощью методов add() и update() можно добавлять новые элементы в множество: t.add(‘x’) # Добавит единственный элемент s.update([10,37,42]) # Добавит несколько элементов в множество s Удалить элемент множества можно с помощью метода remove(): t.remove(‘H’) Словари Словарь – это ассоциативный массив, или таблица хешей, содержащий объекты, индексированные ключами. Чтобы создать словарь, последова- тельность элементов необходимо заключить в фигурные скобки ({}), как показано ниже: stock = { “name” : “GOOG”, “shares” : 100, “price” : 490.10 } Доступ к элементам словаря осуществляется с помощью оператора индек- сирования по ключу: name = stock[“name”] value = stock[“shares”] * stock[“price”] Добавление или изменение объектов в словаре выполняется следующим способом: stock[“shares”] = 75 stock[“date”] = “June 7, 2007” Чаще всего в качестве ключей применяются строки, тем не менее, для этих целей допускается использовать большинство других объектов языка Py- Py- thon, включая числа и кортежи. Определенные объекты, включая списки и словари, не могут использоваться в качестве ключей, потому что их со- держимое может изменяться. Словари обеспечивают удобный способ определения объектов, содержащих именованные поля, как было показано выше. Кроме того, словари могут использоваться, как контейнеры, позволяющие быстро выполнять поиск в неупорядоченных данных. В качестве примера ниже приводится словарь, содержащий цены на акции: Итерации и циклы 37 prices = { “GOOG” : 490.10, “AAPL” : 123.50, “IBM” : 91.50, “MSFT” : 52.13 } Создать пустой словарь можно одним из двух способов: prices = {} # Пустой словарь prices = dict() # Пустой словарь Проверку наличия элемента в словаре можно выполнить с помощью опера- тора in, как показано в следующем примере: if “SCOX” in prices: p = prices[“SCOX”] else: p = 0.0 Данную последовательность действий можно выразить в более компактной форме: p = prices.get(“SCOX”,0.0) Чтобы получить список ключей словаря, словарь можно преобразовать в список: syms = list(prices) # syms = [“AAPL”, “MSFT”, “IBM”, “GOOG”] Для удаления элементов словаря используется инструкция del: del prices[“MSFT”] Словари являются, пожалуй, наиболее оптимизированным типом данных в языке Python. Поэтому если в программе необходимо организовать хра- нение и обработку данных, практически всегда лучше использовать слова- ри, а не пытаться создавать собственные структуры данных. Итерации и циклы Для организации циклов наиболее часто используется инструкция for, ко- торая позволяет выполнить обход элементов коллекции. Итерации – одна из самых богатых особенностей языка Python. Однако наиболее часто ис- Python. Однако наиболее часто ис- . Однако наиболее часто ис- пользуемой формой итераций является простой цикл по элементам после- довательности, такой как строка, список или кортеж. Пример реализации итераций приводится ниже: for n in [1,2,3,4,5,6,7,8,9]: print “2 в степени %d = %d” % (n, 2**n) В данном примере на каждой итерации переменная n будет последователь- но получать значения из списка [1,2,3,4,…,9]. Поскольку необходимость ор- ганизовать цикл по фиксированному диапазону целочисленных значений возникает достаточно часто, для этих целей используется сокращенная форма записи: 38 Глава 1. Вводное руководство for n in range(1,10): print “2 в степени %d = %d” % (n, 2**n) Ф ункция range(i,j [,stride]) создает объект, представляющий диапазон це- лых чисел со значениями от i по j-1. Если начальное значение не указано, оно берется равным нулю. В третьем необязательном аргументе stride мож- но передать шаг изменения значений. Например: a = range(5) # a = 0,1,2,3,4 b = range(1,8) # b = 1,2,3,4,5,6,7 c = range(0,14,3) # c = 0,3,6,9,12 d = range(8,1,-1) # d = 8,7,6,5,4,3,2 Будьте внимательны при использовании функции range() в Python 2, так как в этой версии интерпретатора она создает полный список значений. Для очень больших диапазонов это может привести к ошибке нехватки па- мяти. Поэтому при работе с ранними версиями Python программисты ис- Python программисты ис- программисты ис- пользуют альтернативную функцию xrange(). Например: for i in xrange(100000000): # i = 0,1,2,...,99999999 инструкции Функция xrange() создает объект, который вычисляет очередное значение только в момент обращения к нему. Именно поэтому данный способ явля- ется более предпочтительным при работе с большими диапазонами целых чисел. В версии Python 3 функция xrange() была переименована в range(), а прежняя реализация функции range() была удалена. Возможности инструкции for не ограничиваются последовательностями целых чисел, она также может использоваться для реализации итераций через объекты самых разных типов, включая строки, списки, словари и файлы. Например: a = “Привет, Мир” # Вывести отдельные символы в строке a for c in a: print c ёё b = [“Dave”,”Mark”,”Ann”,”Phil”] # Вывести элементы списка for name in b: print name ёё c = { ‘GOOG’ : 490.10, ‘IBM’ : 91.50, ‘AAPL’ : 123.15 } # Вывести элементы словаря for key in c: print key, c[key] ёё # Вывести все строки из файла f = open(“foo.txt”) for line in f: print line, Цикл for является одной из самых мощных особенностей языка Python, так как позволяет вам создавать собственные объекты-итераторы и функции- генераторы, которые возвращают последовательности значений. Подроб- Функции 39 нее об итераторах и генераторах рассказывается в следующей главе, а так- же в главе 6 «Функции и функциональное программирование». Функции Создание функции производится с помощью инструкции def, как показано в следующем примере: def remainder(a, b): q = a // b # // – оператор деления с усечением дробной части. r = a - q*b return r Чтобы вызвать функцию, достаточно указать ее имя и следующий за ним список аргументов, заключенный в круглые скобки, например: result = re- = re- re- mainder(37, 15) . Если потребуется вернуть из функции несколько значений, можно использовать кортеж, как показано ниже: def divide(a, b): q = a // b # Если a и b – целые числа, q будет целым числом r = a - q*b return (q,r) Когда функция возвращает кортеж с несколькими значениями, его лег- ко можно распаковать в множество отдельных переменных, как показано ниже: quotient, remainder = divide(1456, 33) Присвоить аргументу функции значение по умолчанию можно с помощью оператора присваивания: def connect(hostname, port, timeout=300): # Тело функции Если в определении функции для каких-либо параметров указаны значе- ния по умолчанию, при последующих вызовах функции эти параметры можно опустить. Если при вызове какой-то из этих параметров не указан, он получает значение по умолчанию. Например: connect(‘www.python.org’, 80) Также имеется возможность передавать функции именованные аргумен- ты, которые при этом можно перечислять в произвольном порядке. Однако в этом случае вы должны знать, какие имена аргументов указаны в опреде- лении функции. Например: connect(port=80, hostname=”www.python.org”) Когда внутри функции создаются новые переменные, они имеют локаль- ную область видимости. То есть такие переменные определены только в пределах тела функции, и они уничтожаются, когда функция возвра- щает управление вызывающей программе. Чтобы иметь возможность из- менять глобальные переменные внутри функции, эти переменные следует определить в теле функции с помощью инструкции global: 40 Глава 1. Вводное руководство count = 0 ... def foo(): global count count += 1 # Изменяет значение глобальной переменной count Генераторы Вместо единственного значения функция, с помощью инструкции yield, может генерировать целые последовательности результатов. Например: def countdown(n): print “Обратный отсчет!” while n > 0: yield n # Генерирует значение (n) n -= 1 Любая функция, которая использует инструкцию yield, называется гене- ратором . При вызове функции-генератора создается объект, который по- зволяет получить последовательность результатов вызовом метода next() (или __next__() в Python 3). Например: >>> c = countdown(5) >>> c.next() Обратный отсчет! 5 >>> c.next() 4 >>> c.next() 3 >>> Метод next() заставляет функцию-генератор выполняться, пока не будет достигнута следующая инструкция yield. После этого метод next() воз- вращает значение, переданное инструкции yield, и выполнение функции приостанавливается. При следующем вызове метода next() функция про- должит выполнение, начиная с инструкции, следующей непосредственно за инструкцией yield. Этот процесс продолжается, пока функция не вернет управление. Как правило, метод next() не вызывается вручную, как это было показано выше. Вместо этого функция-генератор обычно используется в инструк- ции цикла for, например: >>> for i in countdown(5): ... print i, Обратный отсчет! 5 4 3 2 1 >>> Генераторы обеспечивают чрезвычайно широкие возможности при конвей- ерной обработке или при работе с потоками данных. Например, следую- щая функция-генератор имитирует поведение команды tail -f, которая ча- Сопрограммы 41 сто используется в операционной системе UNIX для мониторинга файлов журналов: # следит за содержимым файла (на манер команды tail -f) import time def tail(f): f.seek(0,2) # Переход в конец файла while True: line = f.readline() # Попытаться прочитать новую строку текста if not line: # Если ничего не прочитано, time.sleep(0.1) # приостановиться на короткое время continue # и повторить попытку yield line Ниже приводится пример генератора, который отыскивает определенную подстроку в последовательности строк: def grep(lines, searchtext): for line in lines: if searchtext in line: yield line Ниже приводится пример, в котором объединены оба эти генератора с це- лью реализовать простейшую конвейерную обработку: # Реализация последовательности команд “tail -f | grep python” # на языке Python wwwlog = tail(open(“access-log”)) pylines = grep(wwwlog,”python”) for line in pylines: print line, Одна из важных особенностей генераторов состоит в том, что они могут ис- пользоваться вместо других итерируемых объектов, таких как списки или файлы. В частности, когда вы пишете такую инструкцию, как for item in s, имя s может представлять список элементов, строки в файле, результат вы- зова функции-генератора или любой другой объект, поддерживающий ите- рации. Возможность использования самых разных объектов под именем s может оказаться весьма мощным инструментом создания расширяемых программ. Сопрограммы Обычно функции оперируют единственным набором входных аргумен- тов. Однако функцию можно написать так, что она будет действовать, как программа, обрабатывающая последовательность входных данных. Такие функции называются сопрограммами, а создаются они с помощью инструкции yield, используемой в выражении (yield), как показано в сле- дующем примере: def print_matches(matchtext): print “Поиск подстроки”, matchtext while True: line = (yield) # Получение текстовой строки 42 Глава 1. Вводное руководство if matchtext in line: print line Чтобы воспользоваться описанной функцией, сначала необходимо вы- звать ее, затем добиться перемещения потока выполнения до первой ин- струкции (yield), а потом начать передачу данных с помощью метода send() . Например: >>> matcher = print_matches(“python”) >>> matcher.next() # Перемещение до первой инструкции (yield) Поиск подстроки python >>> matcher.send(“Hello World”) >>> matcher.send(“python is cool”) python is cool >>> matcher.send(“yow!”) >>> matcher.close() # Завершение работы с объектом matcher >>> Выполнение сопрограммы приостанавливается до тех пор, пока ей не будет передано новое значение с помощью метода send(). Когда это произойдет, выражение (yield) внутри сопрограммы вернет полученное значение и ее работа продолжится со следующей инструкции. Сопрограмма будет вы- полняться, пока не будет встречено следующее выражение (yield) – в этой точке выполнение функции будет приостановлено. Этот процесс будет про- должаться, пока либо сопрограмма сама не вернет управление, либо пока не будет вызван метод close(), как было показано в предыдущем примере. Сопрограммы удобно использовать при разработке многозадачных про- грамм, работа которых укладывается в схему «производитель-потреби- тель», когда одна часть программы производит некоторые данные, а другая часть потребляет их. В этой схеме сопрограммам отводится роль «потреби- теля» данных. Ниже приводится пример программы, в которой совместно действуют генератор и сопрограмма: # Множество сопрограмм поиска matchers = [ print_matches(“python”), print_matches(“guido”), print_matches(“jython”) ] ёё # Подготовка всех подпрограмм к последующему вызову метода next() for m in matchers: m.next() ёё # Передать активный файл журнала всем сопрограммам. # Обратите внимание: для нормальной работы необходимо, # чтобы веб-сервер активно записывал данные в журнал. wwwlog = tail(open(“access-log”)) for line in wwwlog: for m in matchers: m.send(line) # Передача данных каждой из сопрограмм Дополнительная информация о сопрограммах приводится в главе 6. Объекты и классы 43 Объекты и классы Все значения, используемые программами, являются объектами. Объект содержит некоторые внутренние данные и обладает методами, позволяю- щими выполнять различные операции над этими данными. Вам уже при- ходилось использовать объекты и методы, когда вы работали с данными встроенных типов, такими как строки и списки. Например: items = [37, 42] # Создание списка объектов items.append(73) # Вызов метода append() Функция dir() выводит список всех методов объекта и является удобным инструментом для проведения экспериментов в интерактивной оболочке. Например: >>> items = [37, 42] >>> dir(items) [‘__add__’, ‘__class__’, ‘__contains__’, ‘__delattr__’, ‘__delitem__’, ... ‘append’, ‘count’, ‘extend’, ‘index’, ‘insert’, ‘pop’, ‘remove’, ‘reverse’, ‘sort’] >>> При исследовании объектов можно заметить уже знакомые методы, такие как append() и insert(). Кроме того, в списках можно также увидеть специ- альные методы, имена которых всегда начинаются и заканчиваются двумя символами подчеркивания. Эти методы реализуют различные операторы языка. Например, метод __add__() реализует оператор +: >>> items.__add__([73,101]) [37, 42, 73, 101] >>> Для определения новых типов объектов и в объектно-ориентированном программировании используется инструкция class. Например, ниже при- водится определение простого класса стека, обладающего методами push(), pop() и length(): class Stack(object): def __init__(self): # Инициализация стека self.stack = [ ] def push(self,object): self.stack.append(object) def pop(self): return self.stack.pop() def length(self): return len(self.stack) В первой строке определения класса инструкция class Stack(object) объяв- ляет, что Stack – это объект. В круглых скобках указывается, наследником какого класса является объявляемый класс; в данном случае класс Stack наследует свойства и методы класса object, который является родоначаль- ником всех типов данных в языке Python. Внутри объявления класса опре- Python. Внутри объявления класса опре- . Внутри объявления класса опре- деляются методы, с помощью инструкции def. Первый аргумент любого ме- 44 Глава 1. Вводное руководство тода всегда ссылается на сам объект. В соответствии с соглашениями этому аргументу обычно дается имя self. Все методы, выполняющие операции над атрибутами объекта, должны явно ссылаться на переменную self. Методы, имена которых начинаются и заканчиваются двумя символами подчерки- вания, являются специальными методами. Например, метод __init__() ис- пользуется для инициализации объекта после его создания. Ниже приводится пример использования класса: s = Stack() # Создать стек s.push(“Dave”) # Поместить на стек некоторые данные s.push(42) s.push([3,4,5]) x = s.pop() # переменная x получит значение [3,4,5] y = s.pop() # переменная y получит значение 42 del s # Уничтожить объект s В этом примере был создан совершенно новый объект, реализующий стек. Однако по своей природе стек очень похож на встроенный тип списка. По- этому можно было бы унаследовать класс list и добавить один дополни- тельный метод: class Stack(list): # Добавить метод push() интерфейса стека # Обратите внимание: списки уже имеют метод pop(). def push(self,object): self.append(object) Обычно все методы, присутствующие в объявлении класса, могут приме- няться только к экземплярам данного класса (то есть к созданным объ- ектам). Однако существует возможность определять методы различных видов, например статические, знакомые программистам по языкам C++ и Java: class EventHandler(object): @staticmethod def dispatcherThread(): while (1): # Ожидание запроса ... ёё EventHandler.dispatcherThread() # Вызов метода как обычной функции В данном случае @staticmethod объявляет следующий за ним метод стати- ческим. @staticmethod – это пример использования декоратора, подробнее о которых будет рассказываться в главе 6. Исключения При возникновении ошибки в программе возбуждается исключение и вы- водится трассировочная информация, такая, как показано ниже: Traceback (most recent call last): File “foo.py”, line 12, in IOError: [Errno 2] No such file or directory: ‘file.txt’ Исключения 45 (Перевод: Трассировочная информация (самый последний вызов – самый нижний): Файл “foo.py”, строка 12, в <модуль> IOError: [Errno 2] Нет такого файла или каталога: ‘file.txt’ ) Т рассировочная информация позволяет определить тип ошибки и место, где она возникла. Обычно ошибки приводят к аварийному завершению программы. Однако имеется возможность перехватить и обработать ис- ключение – с помощью инструкций try и except, как показано ниже: try: f = open(“file.txt”,”r”) except IOError as e: print e Если будет возбуждено исключение IOError, информация о причинах по- явления ошибки будет записана в переменную e и управление будет пере- дано первой инструкции в блоке except. Если возникнет какое-то другое исключение, оно будет передано объемлющему блоку кода (если таковой имеется). Если операция выполнена без ошибок, инструкции в блоке except будут просто игнорироваться. После обработки исключения выполнение программы продолжится с первой инструкции, следующей за последней инструкцией в блоке except. Программа не возвращается в то место, где воз- никло исключение. Возбудить исключение вручную можно с помощью инструкции raise. Для этого инструкции raise можно передать один из встроенных классов ис- ключений, например: raise RuntimeError(“Компьютер говорит нет”) Или создать и использовать собственный класс исключения, как описано в разделе «Определение новых исключений» в главе 5 «Структура програм- мы и управление потоком выполнения». Управление системными ресурсами, такими как блокировки, файлы и се- тевые соединения, часто является достаточно сложным делом, особенно когда при этом необходимо предусматривать обработку исключений. Упро- стить решение таких задач программирования можно с помощью инструк- ции with, применяя ее к объектам определенного типа. Ниже приводится пример программного кода, который использует мьютекс в качестве бло- кировки: import threading message_lock = threading.Lock() ... with message_lock: messages.add(newmessage) В этом примере при выполнении инструкции with автоматически приобре- тается объект блокировки message_lock. Когда поток выполнения покидает контекст блока with, блокировка автоматически освобождается. Благодаря этому обеспечивается надежное управление блокировкой, независимо от того, что происходит внутри блока with. Например, даже если при выпол- 46 Глава 1. Вводное руководство нении инструкций внутри блока возникнет исключение, блокировка все равно будет освобождена после выхода за его пределы. Обычно инструкция with совместима только с объектами, представляю- щими те или иные системные ресурсы или среду выполнения, такие как файлы, соединения и блокировки. Однако имеется возможность реализо- вать поддержку этой инструкции в своих классах. Подробнее об этом рас- сказывается в разделе «Протокол управления контекстом» главы 3 «Типы данных и объекты». Модули Часто по мере роста программы возникает желание разбить ее на несколь- ко файлов, чтобы упростить ее разработку и дальнейшее сопровождение. Язык Python позволяет помещать определения в файлы и использовать их как модули, которые могут импортироваться другими программами и сце- нариями. Чтобы создать модуль, необходимо поместить соответствующие инструкции и определения в файл с тем же именем, которое будет присвое- но модулю. (Обратите внимание, что имя файла должно иметь расширение .py .) Например: # файл : div.py def divide(a, b): q = a/b # Если a и b – целые числа, q будет целым числом r = a - q*b return (q, r) Использовать модуль в других программах можно с помощью инструкции import : import div a, b = div.divide(2305, 29) Инструкция import создает новое пространство имен и внутри этого про- странства имен выполняет все инструкции, находящиеся в файле с рас- ширением .py. Чтобы получить доступ к содержимому этого пространства имен после импортирования, достаточно просто использовать имя моду- ля в качестве префикса, как это сделано в вызове функции div.divide() в преды дущем примере. Если потребуется импортировать модуль под другим именем, достаточно добавить в инструкцию import дополнительный квалификатор as, как по- казано ниже: import div as foo a,b = foo.divide(2305,29) Чтобы импортировать некоторые определения в текущее пространство имен, можно воспользоваться инструкцией from: from div import divide a,b = divide(2305,29) # Префикс div больше не нужен Чтобы загрузить в текущее пространство имен все содержимое модуля, можно использовать следующий прием: Получение справки 47 from div import * При вызове функции dir() с именем модуля она выведет содержимое ука- занного модуля, что делает эту фунцию удобным инструментом для экспе- риментов в интерактивной оболочке: >>> import string >>> dir(string) [‘__builtins__’, ‘__doc__’, ‘__file__’, ‘__name__’, ‘_idmap’, ‘_idmapL’, ‘_lower’, ‘_swapcase’, ‘_upper’, ‘atof’, ‘atof_error’, ‘atoi’, ‘atoi_error’, ‘atol’, ‘atol_error’, ‘capitalize’, ‘capwords’, ‘center’, ‘count’, ‘digits’, ‘expandtabs’, ‘find’, ... >>> Получение справки При работе с интерпретатором Python у вас всегда под рукой будет несколь- Python у вас всегда под рукой будет несколь- у вас всегда под рукой будет несколь- ко источников справочной информации. Во-первых, при работе в интерак- тивном режиме с помощью команды help() можно получить информацию о любом встроенном модуле и о других аспектах языка Python. Можно про- Python. Можно про- . Можно про- сто ввести команду help() и получить общую справочную информацию или команду help(‘имя_модуля’), чтобы получить информацию о конкретном мо- дуле. Если команде help() передать имя определенной функции, она может вернуть информацию об этой функции. Большинство функций в языке Python снабжены строками документиро- Python снабжены строками документиро- снабжены строками документиро- вания, описывающими порядок их использования. Чтобы вывести стро- ку документирования, достаточно просто вывести содержимое атрибута __doc__ . Например: >>> print issubclass.__doc__ issubclass(C, B) -> bool ёё Return whether class C is a subclass (i.e., a derived class) of class B. When using a tuple as the second argument issubclass(X, (A, B, ...)), is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.). (Перевод Проверяет, является ли класс C подклассом (то есть наследует) класса B. Когда во втором аргументе передается кортеж – issubclass(X, (A, B, ...)), такой вызов является сокращенным вариантом issubclass(X, A) or issubclass(X, B) or ... (и т. д.). ) >>> И последнее, но также важное замечание – большинство инсталляций Py- Py- thon включает также команду pydoc, которая может использоваться для получения документации о модулях Python. Для этого достаточно просто ввести команду pydoc topic в системной командной строке. |