Средства управления логикой
Кроме только что представленной инструкции while, в языке Python присутствуют другие привычные средства управления логикой программы с небольшими изменениями.
🕛 11.07.2009, 13:14
Инструкция ifПожалуй, наиболее известной является инструкция if:
>>> x = int(raw_input("Введите, пожалуйста, число: "))
>>> if x < 0:
... x = 0
... print 'Отрицательное, меняем на ноль'
... elif x == 0:
... print 'Ноль'
... elif x == 1:
... print 'Один'
... else:
... print 'Больше'
...
Ветвь elif может, как совсем отсутствовать, так и присутствовать несколько раз; наличие ветви else необязательно. Ключевое слово elif является короткой формой для else if и позволяет избежать чрезмерных отступов. Последовательность if ... elif ... elif ... эквивалентна инструкциям switch и case в других языках.
Инструкция for
Инструкция for в языке Python немного отличается от того, что используется в таких языках как C или Pascal. Вместо того, чтобы всегда перебирать числа арифметической прогрессии (как в Pascal), или предоставлять пользователю полную свободу выбора итератора и условия выхода из цикла (как в С), перебирает элементы произвольной последовательности (например, списка или строки) в порядке их следования (с формальной точки зрения это не совсем так: в языке Python под последовательностью всегда подразумевается последовательность с произвольным доступом; средства для работы с последовательностями (в том числе и инструкция for) требует возможности получить произвольный элемент по индексу.):
>>> # Измерение нескольких строк:
... a = ['кот', 'окно', 'выбросить']
>>> for x in a:
... print x, len(x)
...
кот 3
окно 4
выбросить 9
Небезопасно изменять в цикле итерируемую последовательность (такое возможно только для последовательностей, допускающих изменение, например, списков). Если Вы собираетесь вносить изменения в список, элементы которого перебираете, например, продублировать избранные элементы, следует перебирать элементы копии исходного списка. Запись в виде среза делает это особенно удобным:
>>> for x in a[:]: # сделать копию (среза) всего списка
... if len(x) > 4: a.insert(0, x)
...
>>> for x in a:
... print x,
...
выбросить кот окно выбросить
Используя средства функционального программирования (см. раздел 5.2), можно одновременно перебирать элементы нескольких последовательностей.
Функции range() и xrange()
Если Вам необходимо перебирать последовательность чисел, то пригодится встроенная функция range(). Она создает список, содержащий арифметическую прогрессию:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Указанная верхняя граница никогда не входит в созданную последовательность. range(10) создает список из 10 значений, точно соответствующих допустимым индексам для элементов последовательности, имеющей длину 10. Можно указать другую нижнюю границу или другое приращение (шаг), в том числе и отрицательное:
>>> range(5, 10)
[5, 6, 7, 8, 9]
>>> range(0, 10, 3)
[0, 3, 6, 9]
>>> range(-10, -100, -30)
[-10, -40, -70]
Для того, чтобы перебрать индексы последовательности, используйте совместно range() и len():
>>> a = ['У', 'Марии', 'есть', 'маленькая', 'овечка']
>>> for i in range(len(a)):
... print i, a
...
0 У
1 Марии
2 есть
3 маленькая
4 овечка
Дотошный читатель может заметить, что если нужно перебирать числа большого диапазона, создание списка будет неоправданно, а в некоторых случаях просто не хватит памяти:
>>> l=range(10000000)
Traceback (innermost last): File "<stdin>", line 1, in ?
MemoryError
Действительно, если мы не собираемся изменять список, достаточно создать псевдосписок - объект, для которого мы можем получить значения "элементов", но не можем изменить их или порядок их следования. Для этих целей в языке Python предусмотрена функция xrange():
>>> xrange(5, 10)
(5, 6, 7, 8, 9)
>>> xrange(0, 10, 3)
(0, 3, 6, 9)
>>> xrange(-10, -100, -30)
(-10, -40, -70)
>>> a = ['У', 'Марии', 'есть', 'маленькая', 'овечка']
>>> for i in xrange(len(a)):
... print i, a
...
0 У
1 Марии
2 есть
3 маленькая
4 овечка
Инструкции break и continue, ветвь else в циклах
Инструкция break, как и в C, выходит из самого внутреннего вложенного цикла for или while. Инструкция continue, также позаимствованная из C, продолжает выполнение цикла со следующей итерации.
Циклы могут иметь ветвь else, которая выполняется при "нормальном" выходе (исчерпание последовательности в цикле for, неудовлетворение условия в цикле while), без прерывания инструкцией break. Продемонстрируем ее использование на примере поиска простых чисел:
>>> for n in xrange(2, 10):
... for x in xrange(2, n):
... if n % x == 0:
... print n, '=', x, '*', n/x
... break
... else:
... print n, '- простое число'
...
2 - простое число
3 - простое число
4 = 2 * 2
5 - простое число
6 = 2 * 3
7 - простое число
8 = 2 * 4
9 = 3 * 3
4.5. Инструкция pass
Инструкция pass ничего не делает и может быть использована там, где инструкция требуется синтаксисом языка, однако действий никаких выполнять не требуется:
>>> while 1:
... pass # Ожидание прерывания от клавиатуры
...
Определение функций
Мы можем создать функцию, которая будет выводить последовательность чисел Фибоначчи с произвольной верхней границей:
>>> def fib(n):
... '''Выводит последовательность чисел Фибоначчи,
... не превышающих n'''
... a, b = 0, 1
... while b < n:
... print b,
... a, b = b, a+b
...
>>> # Теперь вызовем только что определенную функцию
... fib(2000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
Ключевое слово def представляет определение функции. После него должно следовать имя функции и, в скобках, список формальных параметров. Инструкции, образующие тело функции, записываются с отступом, начиная со следующей строки. Первой инструкцией тела функции может быть строка документации (см. раздел 4.7.5). Существуют средства для автоматического создания документации, а также средства, позволяющие пользователю просматривать строки документации в интерактивном режиме. Включение строк документации в код является хорошей традицией.
Выполнение функции вводит новую таблицу имен, используемую для локальных переменных. Точнее, все присваивания переменным в теле функции сохраняются в локальной таблице имен. При ссылке на переменную, ее поиск производится сначала в локальной таблице имен, затем в глобальной и, в последнюю очередь, в таблице встроенных имен. Так, глобальным переменным нельзя прямо присвоить значение в теле функции (не упомянув их перед этим в инструкции global), хотя на них можно ссылаться.
Аргументы функции в момент вызова помещаются в локальную таблицу имен вызываемой функции. Таким образом, аргументы передаются по значению (где значение всегда является ссылкой на объект, а не его значением) [На самом деле, правильнее было бы сказать, что аргументы передаются по ссылке на объект: если передается объект, допускающий изменения, то изменения (например, добавление элементов в список) будут видны в том месте, откуда функция была вызвана.]. В случае вызова функции другой функцией, также создается новая локальная таблица имен для этого вызова.
Определение функции вводит имя этой функции в текущую таблицу имен. Значение имени функции имеет тип, распознаваемый интерпретатором как определенная пользователем функция. Это значение может быть присвоено другому имени, которое затем также можно использовать в качестве функции (механизм переименования):
>>> fib
<function object at 10042ed0>
>>> f = fib
>>> f(100)
1 1 2 3 5 8 13 21 34 55 89
Вы можете возразить, что fib является процедурой, а не функцией. В языке Python, как и в C, процедура - всего лишь функция, которая не возвращает никакого значения. Строго говоря, процедуры все же возвращают значение, которое, скорее, не представляет большого интереса. Это значение - None (встроенное имя). Значение None обычно не выводится интерпретатором, но Вы можете его увидеть, если действительно хотите этого:
>>> print fib(0)
None
Довольно просто написать функцию, которая возвращает список чисел ряда Фибоначчи, вместо того, чтобы выводить их:
>>> def fib2(n):
... '''Возвращает список, содержащий числа ряда
... Фибоначчи, не превышающие n'''
... result = []
... a, b = 0, 1
... while b < n:
... result.append(b)
... a, b = b, a+b
... return result
...
>>> # Вызываем только что определенную функцию
... f100 = fib2(100)
>>> # Выводим результат
... f100
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Этот пример, как обычно, демонстрирует несколько новых особенностей языка Python:
* Инструкция return выходит из функции и возвращает значение. Без аргументов return используется для выхода из середины процедуры (иначе выход происходит при достижении конца процедуры), в этом случае возвращается значение None. * Инструкция result.append(b) вызывает метод объекта-списка result. Метод-это функция, "принадлежащая" объекту, вызывается как obj.methodname, где obj - объект (или выражение его определяющее) и methodname - имя метода, определенного для данного типа объектов. Различные типы имеют различные наборы методов. Методы различных типов могут иметь одинаковые имена, не приводя к неопределенности. (Вы можете определить собственные типы объектов - классы - и методы работы с ними.) Метод append(), используемый в примере, определен для объектов-списков. Он добавляет элемент в конец списка. В приведенном примере его использование эквивалентно записи 'result = result + ', но более эффективно.