Цикл for: примеры и возможные ошибки
В информатике цикл for используется для того, чтобы сделать однотипные действия много раз. Например, вывести товар из списка один за другим, перебрать числа в некотором диапазоне и выполнить соответствующий скрипт для каждого из них.
Цикл for, в отличие от while, используется наиболее часто. Оба варианта существуют во всех языках программирования. В ряде ЯП он синтаксически и семантически идентичен.
В python цикл for состоит из:
- оператора for;
- имени назначаемой переменной;
- обрабатываемого списка;
- тела функции и дополнительных операторов.
В отличие от Си-подобных языков, инструкции не отделяются фигурными скобками {}. Для этого используется оператор “:” после блока условий и табулирование в теле цикла. Без отступа tab код не сработает и появится ошибка.
В качестве дополнительных операторов применяются continue, break, pass - указатели на пропуск итерации, окончание цикла, пропуск итерации. Они указываются после блока некоторых условий if-else.
Цикл for
Такой цикл используется для перебора всех элементов коллекции. Задается в формате
for переменная in список: инструкция
Он напоминает цикл foreach из C++
foreach (type item in set) {};
for i in 'hello world':
print(i * 2, end='')
hheelllloo wwoorrlldd
В Пайтоне цикл for является совместным - указания в теле выполняются для каждого члена списка без явного указания последовательности. Исполнение инструкции происходит в наиболее оптимальном порядке.
Переменной i присваивается каждый объект из коллекции. Элементы списка могут быть числовыми и строковыми, но обязательно целочисленного типа. При работе с многомерными массивами под переменной i будут пониматься вложенные массивы.
list_of_lists = [['hammerhead', 'great white', 'dogfish'],[0, 1, 2],[9.9, 8.8, 7.7]]
for list in list_of_lists:
print(list)
['hammerhead', 'great white', 'dogfish']
[0, 1, 2]
[9.9, 8.8, 7.7]
Чтобы вывести на экран каждый элемент вложенного массива, необходимо использовать вложенные циклы.
Continue
Оператор позволяет пропустить часть цикла for и перейти к следующей итерации. Это осуществляется при возникновении внешнего фактора. Continue указывается после дополнительного блока if, но само условие - внутри цикла перед основной инструкцией.
number = 0
for number in range(10):
number = number + 1
if number == 5:
continue # вот оператор continue
print(str(number))
print('End')
Каждый number в списке значений от 0 до 10 инкрементирует переменную number, которая изначально равняется нулю. Когда number получит значение 5, цикл прервется и начнется выполнение следующей итерации. Получится:
1
2
3
4
6
7
8
9
10
End
Break
Оператор используется совместно с условием if. Такая конструкция полностью прерывает цикл при возникновении некоторого фактора.
number = 0
for number in range(10):
number += 1
if number == 5:
break # break
print('Number = ' + str(number))
print('Out of loop')
Здесь оператор if определяет условие: если значение переменной number равно 5, цикл обрывается. При каждой итерации выполняется первый метод print() и выводит на экран уведомление
Number = 5.
Когда цикл останавливается оператором break, выполняется следующий метод print().
Другой пример проверяет делится ли второе число на первое без остатка.
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print(n, 'equals', x, '*', n//x)
break
else:
# loop fell through without finding a factor
print(n, 'is a prime number')
В данном случае используется вложенный цикл. Сначала все члены из множества чисел в диапазоне от 2 до 10 принимаются как n. Для каждого n определяется новый список с элементами от 2 до n. Таким образом, у нас есть 8 массивов разной длины. Все элементы из полученных коллекций задаются переменной x. Теперь условие if проверяет, что результатом n / x является целое значение. Если true, цикл обрывается, выводит на экран некоторое сообщение. Если n / x делится с остатком, на экран выводится другое сообщение.
Pass
Оператор нужен для игнорирования дополнительных условий.
number = 0
for number in range(10):
number += 1
if number == 5:
pass
print(str(number))
print('End')
Программа работает так, как будто условия if number == 5 не существует. На мониторе появится
1
2
3
4
5
6
7
8
9
10
End
Видим, что в ходе исполнения оператора pass ничего происходит. Он используется в качестве заглушки только там, где это необходимо синтаксически. Например, при разработке нового класса с методами, которые не нужно реализовывать.
class MyClass(object):
def meth_a(self):
pass
def meth_b(self):
print "I'm meth_b"
У функции meth_a еще нет своей инструкции. Но Python требует, чтобы блоки кода if, except, def, class не были пустыми. В противном случае появится сообщение об ошибке.
IndentationError: expected an indented block.
Вместо этого можно указать pass.
class CompileError(Exception):
pass
Другая цель использования оператора pass - явная инструкция ничего не делать.
Это прослеживается в другом примере цикла for и pass:
for t in range(25):
do(t)
if t == 20:
pass
В этом отрывке кода перебираются элементы списка от 0 до 25. Они рассматриваются как переменная t. При каждой итерации выполняется некоторая функция do(). Если нужно, чтобы на некотором значении вообще ничего не происходило, указывается pass. Например, функция do выводит на экран сообщение 24 раза и пропускает инструкцию на t = 20.
Массивы
Программы с циклом for помогают создавать некоторую последовательность значений и присваивать их переменным.
Возможна такая запись:
for i in [0, 1, 2, 3, 4, 5]:
print i**2
Если бы список имел большее количество элементов, рациональнее было бы создать отдельный массив.
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for in array:
print i
Чтобы создавать списки наподобие
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
,в Пайтон существует функция range(). Метод range() в области параметров принимает три аргумента: начальное значение, конец, шаг. Обязательным является только последний элемент списка. Таким образом, range(5) будет означать, что массив включает числа от 0 до 5. Если указывается шаг, то нужно определить и начальный элемент.
range(0, 10, 2)
Получим:
0, 2, 4, 6, 8, 10
Списки строк
Работа с такими списками аналогична числовым. Например, есть список
colors = ['red', 'green', 'blue', 'yellow']
Разработчики, привыкшие к Си, могут написать следующую функцию.
for i in range(len(colors)):
print colors[i]
Код выполнится без ошибок, но более правильное использование цикла for выглядит так:
colors = ['red', 'green', 'blue', 'yellow']
for color in colors:
print color
Если нужно пройтись по списку от последнего до нулевого значения, используется функция reversed().
colors = ['red', 'green', 'blue', 'yellow']
for color in reversed(colors):
print color
Ошибочной является следующая запись. Опять же, подобное пошло от языка Си.
Списки и индексы
В Пайтоне представлены встроенные функции enumerate() для работы с индексами масивов. Их удобно применять в python циклах for.
В качестве аргументов принимается последовательность значений. Функция enumerate() упрощает использование следующего кода:
for i in range(len(L)):
item = L[i]
# ... compute some result based on item ...
Здесь использован метод len(). Он возвращает количество элементов, в данном случае, массива L. Множество элементов принимается, как аргумент функции range(). Таким образом определяем список [0, … n].
С помощью L[i] получаем доступ к каждому элементу массива L.
L[0], L[1], L[2] и т.д.
Функция enumerate() избавляет от необходимости инициализировать переменную счетчика b и упрощает запись до
for counter, value in enumerate(L):
print(“index : “counter, “value : “value)
Enumerate() возвращает пару счетчик-элемент, поэтому с оператором цикла for указаны две переменные.
Аналогичным являются функции items() и iteritems(), которые используются в качестве методов.
d.items()
d.iteritems()
Два списка
Когда необходимо использовать члены нескольких списков, применяется функция zip().
Она берет список A и список B, делает из них единый zip-объект, который содержит вложенные кортежи. Каждый элемент нового объекта соединяет члены списков A и B и сортирует их по индексу.
zip_object[1] = [A[1], B[1]];
Если на входе zip() указывается 4 массива, элементы зип-массива будут содержать по 4 элемента. Упаковка массивов разной длины не вызовывет ошибку. В новый объект будут помещены только такие элементы, которые содержат значение-пару.
Чтобы включить в кортеж каждый элемент, даже тот, у которого нет пары, используется zip_longest().
list(itertools.zip_longest((1,2,3), [4]))
#[(1, 4), (2, None), (3, None)]
Сортировка по ключу
Когда нужно не просто пройтись по элементам массива, а модифицировать его, применятся функция keys().
Метод дублирует и возвращает список доступных ключей словаря.
for k in d.keys():
if k.startswith('R'):
del d[k]
Имеется массив d. Его элементы копируются методом keys(). Каждый элемент является переменной k. Она обрабатывается с помощью startswith, при совпадении элемент удаляется из главного массива.
startswith() возвращает флаг, который проверяет начинается ли строка с указанного префикса. Функция имеет три аргумента: prefix, start, end.
str.startswith(prefix[, start[, end]]) -> bool
Обязательным является только первый - prefix. Им может быть строка либо кортеж.
my_str.startswith(‘value’)
или
my_str.startswith((‘value1’, ‘value2’))
Если в поле параметров необходимо указать несколько строк, элементы оборачиваются в дополнительные скобки ().
Аргумент start указывает на индекс элемента, с которого начинается отсчет. Поддерживаются положительные и отрицательные значения. Если start = -x, то поиск начинается с элемента под индексом x с конца. Параметр end обозначает последний символ, на котором прекращается анализ строки. Он тоже поддерживает отрицательные значения. При end = -x последним будет член списка под индексом x с начала.
По аналогии со startswith() работает функция endswith(). Она проверяет то, заканчивается ли строка указанным постфиксом. У нее есть три параметра suffix, start, end, возвращает также булевое значение.
Объединение списков
Если нужно соединить элементы двух массивов, наиболее быстрый способ - использовать связку методов dict(izip(массив 1, массив 1)). В этом случае элементы располагаются не последовательно друг за другом, а в виде:
‘элемент массива 1’ : ‘элемент массива 2’
names = ['raymond', 'rachel', 'matthew']
colors = ['red', 'green', 'blue']
d = dict(zip(names, colors))
# {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
Метод dict() создает словарь, внутрь которого помещаются значения вышеуказанным способом - через “:”. В качестве основного значения используется элемент массива 2. Чтобы его вызвать, к нему нужно обратиться по индексу - значение массива 1.
d[‘raymond’]
# red
Подсчет членов списка
Чтобы узнать, из какого количества элементов состоит список, используется функция get().
d.get(key, default = None)
Этим методом проверяет словарь d на наличие key, возвращается индекс key[index].
colors = ['red', 'green', 'red', 'blue', 'green', 'red']
d = {}
for color in colors:
d[color] = d.get(color, 0) + 1
Метод get() является более удобным и быстрым аналогом следующего кода.
colors = ['red', 'green', 'red', 'blue', 'green', 'red']
d = {}
for color in colors:
if color not in d:
d[color] = 0
d[color] += 1
Это основные примеры и возможные ошибки цикла for.