>>> some_list = []
>>> if some_list:
…·····print("There's something in here")
… else:
…·····print("Hey, it's empty!")
…
Hey, it's empty!
Если вы выполняете проверку для выражения, а не для простой переменной, Python оценит его значение и вернет булев результат. Поэтому, если вы введете следующее:
if color == "red":
Python оценит выражение color == "red". В нашем примере мы присвоили переменной color значение "puce", поэтому значение выражения color == "red" равно False и Python перейдет к следующей проверке:
elif color == "green":
Повторяем действия с помощью while
Проверки с помощью if, elif и else выполняются последовательно. Иногда нам нужно выполнить какие-то операции более чем один раз. Нам нужен цикл, и простейшим вариантом циклов в Python является while. Попробуйте запустить с помощью интерактивного интерпретатора следующий пример — это простейший цикл, который выводит на экран значения от 1 до 5:
>>> count = 1
>>> while count <= 5:
…·····print(count)
…·····count += 1
…
1
2
3
4
5
>>>
Сначала мы присваиваем значение 1 переменной count. Цикл while сравнивает значение переменной count с числом 5 и продолжает работу, если значение переменной count меньше или равно 5. Внутри цикла мы выводим значение переменной count, а затем увеличиваем его на 1 с помощью выражения count += 1. Python возвращается к верхушке цикла и снова сравнивает значение переменной count с числом 5. Значение переменной count теперь равно 2, поэтому содержимое цикла while выполняется снова и переменная count увеличивается до 3.
Это продолжается до тех пор, пока переменная count не будет увеличена с 5 до 6 в нижней части цикла. Во время очередного возврата наверх цикла проверка count <= 5 вернет значение False и цикл while закончится. Python перейдет к выполнению следующих строк.
Прерываем цикл с помощью break
Если вы хотите, чтобы цикл выполнялся до тех пор, пока что-то не произойдет, но вы не знаете точно, когда это событие случится, можете воспользоваться бесконечным циклом, содержащим оператор break. В этот раз мы считаем строку с клавиатуры с помощью функции input(), а затем выведем ее на экран, сделав первую букву прописной. Мы прервем цикл, когда будет введена строка, содержащая только букву «q»:
>>> while True:
…·····stuff = input("String to capitalize [type q to quit]: ")
…·····if stuff == "q":
…·········break
…·····print(stuff.capitalize())
…
String to capitalize [type q to quit]: test
Test
String to capitalize [type q to quit]: hey, it works
Hey, it works
String to capitalize [type q to quit]: q
>>>
Пропускаем итерации с помощью continue
Иногда вам нужно не прерывать весь цикл, а только пропустить по какой-то причине одну итерацию. Рассмотрим воображаемый пример: считаем целое число, выведем на экран его значение в квадрате, если оно четное, и пропустим его, если оно нечетное. Мы даже добавим несколько комментариев. И вновь для выхода из цикла используем строку "q":
>>> while True:
…·····value = input("Integer, please [q to quit]: ")
…·····if value == 'q':······# выход
…·········break
…·····number = int(value)
…·····if number % 2 == 0:···# нечетное число
…········continue
…·····print(number, "squared is", number*number)
…
Integer, please [q to quit]: 1
1 squared is 1
Integer, please [q to quit]: 2
Integer, please [q to quit]: 3
3 squared is 9
Integer, please [q to quit]: 4
Integer, please [q to quit]: 5
5 squared is 25
Integer, please [q to quit]: q
>>>
Проверяем, завершился ли цикл заранее, с помощью else
Если цикл while завершился нормально (без вызова break), управление передается в опциональный блок else. Вы можете использовать его в цикле, где выполняете некоторую проверку и прерываете цикл, как только проверка успешно выполняется. Блок else выполнится в том случае, если цикл while будет пройден полностью, но искомый объект не будет найден:
>>> numbers = [1, 3, 5]
>>> position = 0
>>> while position < len(numbers):
…·····number = numbers[position]
…·····if number % 2 == 0:
…·········print('Found even number', number)
…·········break
…·····position += 1
… else:··# break not called
…·····print('No even number found')
…
No even number found
Такое использование ключевого слова else может оказаться нелогичным. Рассматривайте его как проверку на прерывание цикла.
Выполняем итерации с помощью for
В Python итераторы часто используются по одной простой причине. Они позволяют вам проходить структуры данных, не зная, насколько эти структуры велики и как реализованы. Вы даже можете пройти по данным, которые были созданы во время работы программы, что позволяет обработать потоки данных, которые в противном случае не поместились бы в память компьютера.
Вполне возможно пройти по последовательности таким образом:
>>> rabbits = ['Flopsy', 'Mopsy', 'Cottontail', 'Peter']
>>> current = 0
>>> while current < len(rabbits):
…·····print(rabbits[current])
…·····current += 1
…
Flopsy
Mopsy
Cottontail
Peter
Однако существует более характерный для Python способ решения этой задачи:
>>> for rabbit in rabbits:
…·····print(rabbit)
…
Flopsy
Mopsy
Cottontail
Peter
Списки вроде rabbits являются одними из итерабельных объектов в Python наряду со строками, кортежами, словарями и некоторыми другими элементами. Итерирование по кортежу или списку возвращает один элемент за раз. Итерирование по строке возвращает один символ за раз, как показано здесь:
>>> word = 'cat'
>>> for letter in word:
…·····print(letter)
…
c
a
t
Итерирование по словарю (или его функции keys()) возвращает ключи. В этом примере ключи являются типами карт в настольной игре Clue (за пределами Северной Америки она называется CluedoAmerica):
>>> accusation = {'room': 'ballroom', 'weapon': 'lead pipe',
··················'person': 'Col. Mustard'}
>>> for card in accusation:··#··или for card in accusation.keys():
…·····print(card)
…
room
weapon
person
Чтобы итерировать по значениям, а не по ключам, следует использовать функцию values():
>>> for value in accusation.values():
…·····print(value)
…
ballroom
lead pipe
Col. Mustard
Чтобы вернуть как ключ, так и значение кортежа, вы можете использовать функцию items():
>>> for item in accusation.items():
…·····print(item)
…
('room', 'ballroom')
('weapon', 'lead pipe')
('person', 'Col. Mustard')
Помните, что можете присвоить значение кортежу за один шаг. Для каждого кортежа, возвращенного функцией items(), присвойте первое значение (ключ) переменной card, а второе (значение) — переменной contents:
>>> for card, contents in accusation.items():
…·····print('Card', card, 'has the contents', contents)
…
Card weapon has the contents lead pipe
Card person has the contents Col. Mustard
Card room has the contents ballroom
Прерываем цикл с помощью break
Ключевое слово break в цикле for прерывает этот цикл точно так же, как и цикл while.
Пропускаем итерации с помощью continue
Добавление ключевого слова continue в цикл for позволяет перейти на следующую итерацию цикла, как и в случае с циклом while.
Проверяем, завершился ли цикл заранее, с помощью else
Как и в цикле while, в for имеется опциональный блок else, который проверяет, выполнился ли цикл for полностью. Если ключевое слово break не было вызвано, будет выполнен блок else.
Это полезно, если вам нужно убедиться в том, что предыдущий цикл выполнился полностью, вместо того чтобы рано прерваться. Цикл for в следующем примере выводит на экран название сыра и прерывается, если сыра в магазине не найдется:
>>> cheeses = []
>>> for cheese in cheeses:
…·····print('This shop has some lovely', cheese)
…·····break
… else:··# отсутствие прерывания означает, что сыра нет
…·····print('This is not much of a cheese shop, is it?')
…
This is not much of a cheese shop, is it?
Как и в цикле while, в цикле for использование блока else может показаться нелогичным. Можно рассматривать цикл for как поиск чего-то, в таком случае else будет вызываться, если вы ничего не нашли. Чтобы получить тот же эффект без блока else, используйте переменную, которая будет показывать, нашелся ли искомый элемент в цикле for, как здесь:
>>> cheeses = []
>>> found_one = False
>>> for cheese in cheeses:
…·····found_one = True
…·····print('This shop has some lovely', cheese)
…·····break
…
>>> if not found_one:
…·····print('This is not much of a cheese shop, is it?')
…
This is not much of a cheese shop, is it?
Итерирование по нескольким последовательностям с помощью функции zip()
Существует еще один полезный прием — параллельное итерирование по нескольким последовательностям с помощью функции zip():
>>> days = ['Monday', 'Tuesday', 'Wednesday']
>>> fruits = ['banana', 'orange', 'peach']
>>> drinks = ['coffee', 'tea', 'beer']
>>> desserts = ['tiramisu', 'ice cream', 'pie', 'pudding']
>>> for day, fruit, drink, dessert in zip(days, fruits, drinks, desserts):
…·····print(day, ": drink", drink, "eat", fruit, "enjoy", dessert)
…
Monday: drink coffee — eat banana — enjoy tiramisu
Tuesday: drink tea — eat orange — enjoy ice cream
Wednesday: drink beer — eat peach — enjoy pie
Функция zip() прекращает свою работу, когда выполняется самая короткая последовательность. Один из списков (desserts) оказался длиннее остальных, поэтому никто не получит пудинг, пока мы не увеличим остальные списки.
В разделе «Словари» главы 3 показывается, как с помощью функции dict() можно создавать словари из последовательностей, содержащих два элемента, вроде кортежей, списков или строк. Вы можете использовать функцию zip(), чтобы пройти по нескольким последовательностям и создать кортежи из элементов с одинаковыми смещениями. Создадим два кортежа из соответствующих друг другу английских и французских слов:
>>> english = 'Monday', 'Tuesday', 'Wednesday'
>>> french = 'Lundi', 'Mardi', 'Mercredi'
Теперь используем функцию zip(), чтобы объединить эти кортежи в пару. Значение, возвращаемое функцией zip(), само по себе не является списком или кортежем, но его можно преобразовать в любую из этих последовательностей:
>>> list(zip(english, french))
[('Monday', 'Lundi'), ('Tuesday', 'Mardi'), ('Wednesday', 'Mercredi')]
Передайте результат работы функции zip() непосредственно функции dict() — и у нас готов небольшой англо-французский словарь!
>>> dict(zip(english, french))
{'Monday': 'Lundi', 'Tuesday': 'Mardi', 'Wednesday': 'Mercredi'}
Генерирование числовых последовательностей с помощью функции range()
Функция range() возвращает поток чисел в заданном диапазоне без необходимости создавать и сохранять крупную структуру данных вроде списка или кортежа. Это позволяет вам создавать большие диапазоны, не использовав всю память компьютера и не обрушив программу.
Вы можете применять функцию range() аналогично slice(): range(start, stop, step). Если опустите значение start, диапазон начнется с 0. Необходимым является лишь значение stop: как и в случае со slice(), оно определяет последнее значение, которое будет создано прямо перед остановкой функции. Значение по умолчанию step равно 1, но вы можете изменить его на -1.
Как и zip(), функция range() возвращает итерабельный объект, поэтому вам нужно пройти по значениям с помощью конструкции for … in или преобразовать объект в последовательность вроде списка. Создадим диапазон 0, 1, 2:
>>> for x in range(0,3):
…·····print(x)
…
0
1
2
>>> list(range(0, 3))
[0, 1, 2]
Вот так можно создать диапазон от 2 до 0:
>>> for x in range(2, -1, -1):
…·····print(x)
…
2
1
0
>>> list(range(2, -1, -1))
[2, 1, 0]
В следующем фрагменте кода используется шаг 2, чтобы получить все четные числа от 0 до 10:
>>> list(range(0, 11, 2))
[0, 2, 4, 6, 8, 10]
Прочие итераторы
В главе 8 рассматривается итерирование по файлам. В главе 6 вы сможете увидеть, как использовать итерирование для объектов, которые сами определили.
Включения