datastructures.md
1> **Источник:** https://python-all.ru/2.7/tutorial/datastructures.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 5. Структуры данных89В этой главе более подробно рассматриваются некоторые уже изученные темы, а также добавляются новые.1011## 5.1. Подробнее о списках1213Тип данных list имеет ещё несколько методов. Ниже перечислены все методы объектов list:1415#### `list.append(x)`1617Добавляет элемент в конец списка; эквивалентно `a[len(a):] = [x]`.1819#### `list.extend(L)`2021Расширяет список, добавляя все элементы из указанного списка; эквивалентно `a[len(a):] = L`.2223#### `list.insert(i, x)`2425Вставляет элемент на указанную позицию. Первый аргумент – это индекс элемента, перед которым нужно вставить, поэтому `a.insert(0, x)` вставляет в начало списка, а `a.insert(len(a), x)` эквивалентно `a.append(x)`.2627#### `list.remove(x)`2829Удаляет первый элемент списка, значение которого равно *x*. Возникает ошибка, если такого элемента нет.3031#### `list.pop([i])`3233Удаляет элемент по указанной позиции в списке и возвращает его. Если индекс не указан, `a.pop()` удаляет и возвращает последний элемент списка. (Квадратные скобки вокруг *i* в сигнатуре метода указывают, что параметр является необязательным, а не то, что нужно вводить квадратные скобки в этой позиции. Эта нотация часто встречается в Справочнике по библиотеке Python.)3435#### `list.index(x)`3637Возвращает индекс первого элемента в списке, значение которого равно *x*. Если такого элемента нет, возникает ошибка.3839#### `list.count(x)`4041Возвращает количество вхождений *x* в список.4243#### `list.sort(cmp=None, key=None, reverse=False)`4445Сортирует элементы списка на месте (аргументы можно использовать для настройки сортировки; пояснения см. в [`sorted()`](https://python-all.ru/2.7/library/functions.html#sorted)).4647#### `list.reverse()`4849Разворачивает элементы списка на месте.5051Пример, использующий большинство методов списка:5253```python54>>> a = [66.25, 333, 333, 1, 1234.5]55>>> print a.count(333), a.count(66.25), a.count('x')562 1 057>>> a.insert(2, -1)58>>> a.append(333)59>>> a60[66.25, 333, -1, 333, 1, 1234.5, 333]61>>> a.index(333)62163>>> a.remove(333)64>>> a65[66.25, -1, 333, 1, 1234.5, 333]66>>> a.reverse()67>>> a68[333, 1234.5, 1, 333, -1, 66.25]69>>> a.sort()70>>> a71[-1, 1, 66.25, 333, 333, 1234.5]72>>> a.pop()731234.574>>> a75[-1, 1, 66.25, 333, 333]76```7778Вы могли заметить, что методы `insert`, `remove` или `sort`, которые только изменяют список, не выводят возвращаемое значение – они возвращают значение по умолчанию `None`. Это принцип проектирования для всех изменяемых структур данных в Python.7980### 5.1.1. Использование списков в качестве стеков8182Методы списка позволяют легко использовать список как стек, где последний добавленный элемент извлекается первым (последним пришёл – первым ушёл). Чтобы добавить элемент на вершину стека, используйте `append()`. Чтобы извлечь элемент с вершины стека, используйте `pop()` без явного индекса. Например:8384```python85>>> stack = [3, 4, 5]86>>> stack.append(6)87>>> stack.append(7)88>>> stack89[3, 4, 5, 6, 7]90>>> stack.pop()91792>>> stack93[3, 4, 5, 6]94>>> stack.pop()95696>>> stack.pop()97598>>> stack99[3, 4]100```101102### 5.1.2. Использование списков в качестве очередей103104Список также можно использовать как очередь, где первый добавленный элемент извлекается первым (первым пришёл – первым ушёл); однако списки неэффективны для этой цели. Хотя добавление и извлечение элементов с конца списка выполняется быстро, вставка или извлечение с начала списка – медленно (поскольку все остальные элементы приходится сдвигать на одну позицию).105106Для реализации очереди используйте [`collections.deque`](https://python-all.ru/2.7/library/collections.html#collections.deque), который разработан для быстрого добавления и извлечения элементов с обоих концов. Например:107108```python109>>> from collections import deque110>>> queue = deque(["Eric", "John", "Michael"])111>>> queue.append("Terry") # Терри прибывает112>>> queue.append("Graham") # Грэм прибывает113>>> queue.popleft() # Первый прибывший теперь уходит114'Eric'115>>> queue.popleft() # Второй прибывший теперь уходит116'John'117>>> queue # Оставшаяся очередь в порядке прибытия118deque(['Michael', 'Terry', 'Graham'])119```120121### 5.1.3. Инструменты функционального программирования122123Есть три встроенные функции, которые очень полезны при работе со списками: [`filter()`](https://python-all.ru/2.7/library/functions.html#filter), [`map()`](https://python-all.ru/2.7/library/functions.html#map) и [`reduce()`](https://python-all.ru/2.7/library/functions.html#reduce).124125`filter(function, sequence)` возвращает последовательность, состоящую из тех элементов последовательности, для которых `function(item)` истинно. Если *sequence* является [`str`](https://python-all.ru/2.7/library/functions.html#str), [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode) или [`tuple`](https://python-all.ru/2.7/library/functions.html#tuple), результат будет того же типа; в противном случае это всегда `list`. Например, чтобы вычислить последовательность чисел, делящихся на 3 или 5:126127```python128>>> def f(x): return x % 3 == 0 or x % 5 == 0129...130>>> filter(f, range(2, 25))131[3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24]132```133134`map(function, sequence)` вызывает `function(item)` для каждого элемента последовательности и возвращает список возвращаемых значений. Например, чтобы вычислить несколько кубов:135136```python137>>> def cube(x): return x*x*x138...139>>> map(cube, range(1, 11))140[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]141```142143Может быть передано более одной последовательности; тогда функция должна иметь столько же аргументов, сколько последовательностей, и вызывается с соответствующими элементами из каждой последовательности (или `None`, если какая-то последовательность короче другой). Например:144145```python146>>> seq = range(8)147>>> def add(x, y): return x+y148...149>>> map(add, seq, seq)150[0, 2, 4, 6, 8, 10, 12, 14]151```152153`reduce(function, sequence)` возвращает единственное значение, полученное путём вызова бинарной функции *function* для первых двух элементов последовательности, затем для результата и следующего элемента, и так далее. Например, чтобы вычислить сумму чисел от 1 до 10:154155```python156>>> def add(x,y): return x+y157...158>>> reduce(add, range(1, 11))15955160```161162Если в последовательности только один элемент, возвращается его значение; если последовательность пуста, возбуждается исключение.163164Можно передать третий аргумент, указывающий начальное значение. В этом случае для пустой последовательности возвращается начальное значение, а функция сначала применяется к начальному значению и первому элементу последовательности, затем к результату и следующему элементу, и так далее. Например,165166```python167>>> def sum(seq):168... def add(x,y): return x+y169... return reduce(add, seq, 0)170...171>>> sum(range(1, 11))17255173>>> sum([])1740175```176177Не используйте определение [`sum()`](https://python-all.ru/2.7/library/functions.html#sum) из этого примера: поскольку суммирование чисел – такая распространённая потребность, уже предоставлена встроенная функция `sum(sequence)`, которая работает точно так же.178179### 5.1.4. Списковые включения180181Списковые включения предоставляют краткий способ создания списков. Обычно они используются для создания новых списков, где каждый элемент является результатом некоторых операций, применённых к каждому элементу другой последовательности или итерируемого объекта, или для создания подпоследовательности из элементов, удовлетворяющих определённому условию.182183Например, предположим, мы хотим создать список квадратов, как в:184185```python186>>> squares = []187>>> for x in range(10):188... squares.append(x**2)189...190>>> squares191[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]192```193194Тот же результат можно получить с помощью:195196```python197squares = [x**2 for x in range(10)]198```199200Это также эквивалентно `squares = map(lambda x: x**2, range(10))`, но более кратко и читаемо.201202Списковое включение состоит из квадратных скобок, содержащих выражение, за которым следует предложение [`for`](https://python-all.ru/2.7/reference/compound_stmts.html#for), а затем ноль или более предложений [`for`](https://python-all.ru/2.7/reference/compound_stmts.html#for) или [`if`](https://python-all.ru/2.7/reference/compound_stmts.html#if). Результатом будет новый список, полученный вычислением выражения в контексте следующих за ним предложений [`for`](https://python-all.ru/2.7/reference/compound_stmts.html#for) и [`if`](https://python-all.ru/2.7/reference/compound_stmts.html#if). Например, это списковое включение объединяет элементы двух списков, если они не равны:203204```python205>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]206[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]207```208209и это эквивалентно:210211```python212>>> combs = []213>>> for x in [1,2,3]:214... for y in [3,1,4]:215... if x != y:216... combs.append((x, y))217...218>>> combs219[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]220```221222Обратите внимание, что порядок операторов [`for`](https://python-all.ru/2.7/reference/compound_stmts.html#for) и [`if`](https://python-all.ru/2.7/reference/compound_stmts.html#if) одинаков в обоих фрагментах.223224Если выражение является кортежем (например, `(x, y)` в предыдущем примере), оно должно быть взято в скобки.225226```python227>>> vec = [-4, -2, 0, 2, 4]228>>> # создать новый список с удвоенными значениями229>>> [x*2 for x in vec]230[-8, -4, 0, 4, 8]231>>> # отфильтровать список, чтобы исключить отрицательные числа232>>> [x for x in vec if x >= 0]233[0, 2, 4]234>>> # применить функцию ко всем элементам235>>> [abs(x) for x in vec]236[4, 2, 0, 2, 4]237>>> # вызвать метод для каждого элемента238>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']239>>> [weapon.strip() for weapon in freshfruit]240['banana', 'loganberry', 'passion fruit']241>>> # создать список кортежей из двух элементов вида (число, квадрат)242>>> [(x, x**2) for x in range(6)]243[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]244>>> # кортеж должен быть заключён в скобки, иначе возникнет ошибка245>>> [x, x**2 for x in range(6)]246 File "<stdin>", line 1, in <module>247 [x, x**2 for x in range(6)]248 ^249SyntaxError: invalid syntax250>>> # развернуть список с помощью спискового включения с двумя 'for'251>>> vec = [[1,2,3], [4,5,6], [7,8,9]]252>>> [num for elem in vec for num in elem]253[1, 2, 3, 4, 5, 6, 7, 8, 9]254```255256Списковые включения могут содержать сложные выражения и вложенные функции:257258```python259>>> from math import pi260>>> [str(round(pi, i)) for i in range(1, 6)]261['3.1', '3.14', '3.142', '3.1416', '3.14159']262```263264#### 5.1.4.1. Вложенные списковые включения265266Начальное выражение в списковом включении может быть любым произвольным выражением, включая другое списковое включение.267268Рассмотрим следующий пример матрицы 3x4, реализованной в виде списка из 3 списков длиной 4:269270```python271>>> matrix = [272... [1, 2, 3, 4],273... [5, 6, 7, 8],274... [9, 10, 11, 12],275... ]276```277278Следующее списковое включение транспонирует строки и столбцы:279280```python281>>> [[row[i] for row in matrix] for i in range(4)]282[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]283```284285Как мы видели в предыдущем разделе, вложенное списковое включение вычисляется в контексте [`for`](https://python-all.ru/2.7/reference/compound_stmts.html#for), которое следует за ним, поэтому этот пример эквивалентен:286287```python288>>> transposed = []289>>> for i in range(4):290... transposed.append([row[i] for row in matrix])291...292>>> transposed293[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]294```295296что, в свою очередь, то же самое, что:297298```python299>>> transposed = []300>>> for i in range(4):301... # следующие 3 строки реализуют вложенное списковое включение302... transposed_row = []303... for row in matrix:304... transposed_row.append(row[i])305... transposed.append(transposed_row)306...307>>> transposed308[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]309```310311На практике следует предпочитать встроенные функции сложным управляющим конструкциям. Функция [`zip()`](https://python-all.ru/2.7/library/functions.html#zip) отлично подойдёт для этого случая:312313```python314>>> zip(*matrix)315[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]316```317318Смотрите [Распаковка списков аргументов](https://python-all.ru/2.7/tutorial/controlflow.html#tut-unpacking-arguments) для подробностей об звёздочке в этой строке.319320## 5.2. Инструкция [`del`](https://python-all.ru/2.7/reference/simple_stmts.html#del)321322Существует способ удалить элемент из списка по его индексу, а не по значению: оператор [`del`](https://python-all.ru/2.7/reference/simple_stmts.html#del). Он отличается от метода `pop()`, который возвращает значение. Оператор [`del`](https://python-all.ru/2.7/reference/simple_stmts.html#del) также можно использовать для удаления срезов из списка или очистки всего списка (что мы делали ранее, присваивая срезу пустой список). Например:323324```python325>>> a = [-1, 1, 66.25, 333, 333, 1234.5]326>>> del a[0]327>>> a328[1, 66.25, 333, 333, 1234.5]329>>> del a[2:4]330>>> a331[1, 66.25, 1234.5]332>>> del a[:]333>>> a334[]335```336337[`del`](https://python-all.ru/2.7/reference/simple_stmts.html#del) также можно использовать для удаления целых переменных:338339```python340>>> del a341```342343После этого обращение к имени `a` вызовет ошибку (по крайней мере, пока ему не будет присвоено другое значение). Мы найдём другие применения [`del`](https://python-all.ru/2.7/reference/simple_stmts.html#del) позднее.344345## 5.3. Кортежи и последовательности346347Мы видели, что списки и строки имеют много общих свойств, таких как операции индексирования и нарезки. Это два примера типов данных *последовательность* (см. [Sequence Types – str, unicode, list, tuple, bytearray, buffer, xrange](https://python-all.ru/2.7/library/stdtypes.html#typesseq)). Поскольку Python – развивающийся язык, могут быть добавлены другие типы данных-последовательностей. Существует также ещё один стандартный тип данных-последовательность: *кортеж*.348349Кортеж состоит из нескольких значений, разделенных запятыми, например:350351```python352>>> t = 12345, 54321, 'hello!'353>>> t[0]35412345355>>> t356(12345, 54321, 'hello!')357>>> # Кортежи могут быть вложенными:358... u = t, (1, 2, 3, 4, 5)359>>> u360((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))361>>> # Кортежи неизменяемы:362... t[0] = 88888363Traceback (most recent call last):364 File "<stdin>", line 1, in <module>365TypeError: 'tuple' object does not support item assignment366>>> # но они могут содержать изменяемые объекты:367... v = ([1, 2, 3], [3, 2, 1])368>>> v369([1, 2, 3], [3, 2, 1])370```371372Как видите, при выводе кортежи всегда заключаются в круглые скобки, чтобы вложенные кортежи интерпретировались правильно; их можно вводить как с окружающими скобками, так и без них, хотя скобки часто необходимы (если кортеж является частью более крупного выражения). Присваивать значения отдельным элементам кортежа нельзя, однако можно создавать кортежи, содержащие изменяемые объекты, например списки.373374Хотя кортежи могут казаться похожими на списки, они часто используются в разных ситуациях и для разных целей. Кортежи являются [неизменяемыми](https://python-all.ru/2.7/glossary.html#term-immutable) и обычно содержат гетерогенную последовательность элементов, доступ к которым осуществляется через распаковку (см. далее в этом разделе) или индексацию (или даже по атрибуту в случае [`namedtuples`](https://python-all.ru/2.7/library/collections.html#collections.namedtuple)). Списки являются [изменяемыми](https://python-all.ru/2.7/glossary.html#term-mutable), и их элементы обычно однородны и доступны при переборе списка.375376Особая проблема – создание кортежей, содержащих 0 или 1 элемент: в синтаксисе есть некоторые дополнительные особенности для таких случаев. Пустые кортежи создаются с помощью пустой пары круглых скобок; кортеж с одним элементом создается путем добавления запятой после значения (недостаточно заключить одно значение в скобки). Некрасиво, но эффективно. Например:377378```python379>>> empty = ()380>>> singleton = 'hello', # <-- обратите внимание на завершающую запятую381>>> len(empty)3820383>>> len(singleton)3841385>>> singleton386('hello',)387```388389Оператор `t = 12345, 54321, 'hello!'` является примером *упаковки кортежа*: значения `12345`, `54321` и `'hello!'` упаковываются вместе в кортеж. Возможна и обратная операция:390391```python392>>> x, y, z = t393```394395Это называется, что вполне уместно, *распаковкой последовательности* и работает для любой последовательности в правой части. Распаковка последовательности требует, чтобы список переменных слева имел то же количество элементов, что и длина последовательности. Обратите внимание, что множественное присваивание на самом деле является просто комбинацией упаковки кортежа и распаковки последовательности.396397## 5.4. Множества398399Python также включает тип данных для *множеств*. Множество – это неупорядоченная коллекция без повторяющихся элементов. Основные применения: проверка принадлежности и удаление дубликатов. Объекты-множества также поддерживают математические операции, такие как объединение, пересечение, разность и симметрическая разность.400401Фигурные скобки или функция [`set()`](https://python-all.ru/2.7/library/stdtypes.html#set) могут использоваться для создания множеств. Примечание: для создания пустого множества нужно использовать `set()`, а не `{}`; последнее создает пустой словарь – структуру данных, которую мы обсудим в следующем разделе.402403Вот краткая демонстрация:404405```python406>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']407>>> fruit = set(basket) # создать множество без дубликатов408>>> fruit409set(['orange', 'pear', 'apple', 'banana'])410>>> 'orange' in fruit # быстрая проверка принадлежности411True412>>> 'crabgrass' in fruit413False414415>>> # Демонстрация операций над множествами с уникальными буквами из двух слов416...417>>> a = set('abracadabra')418>>> b = set('alacazam')419>>> a # уникальные буквы в a420set(['a', 'r', 'b', 'c', 'd'])421>>> a - b # буквы, которые есть в a, но нет в b422set(['r', 'd', 'b'])423>>> a | b # Буквы из a или b424set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])425>>> a & b # буквы, которые есть и в a, и в b426set(['a', 'c'])427>>> a ^ b # буквы, которые есть в a или в b, но не в обоих428set(['r', 'd', 'b', 'm', 'z', 'l'])429```430431Аналогично [списковым включениям](https://python-all.ru/2.7/tutorial/datastructures.html#tut-listcomps), также поддерживаются множественные включения:432433```python434>>> a = {x for x in 'abracadabra' if x not in 'abc'}435>>> a436set(['r', 'd'])437```438439## 5.5. Словари440441Еще один полезный тип данных, встроенный в Python, – это *словарь* (см. [Типы отображений – dict](https://python-all.ru/2.7/library/stdtypes.html#typesmapping)). Словари в других языках иногда называют «ассоциативными массивами» или «ассоциативной памятью». В отличие от последовательностей, которые индексируются диапазоном чисел, словари индексируются *ключами*, которые могут быть любого неизменяемого типа; строки и числа всегда могут быть ключами. Кортежи можно использовать в качестве ключей, если они содержат только строки, числа или кортежи; если кортеж содержит любой изменяемый объект прямо или косвенно, его нельзя использовать в качестве ключа. Списки нельзя использовать в качестве ключей, поскольку их можно изменять на месте с помощью присваивания по индексу, присваивания среза или методов типа `append()` и `extend()`.442443Словарь лучше всего представлять как неупорядоченное множество пар *ключ: значение*, при этом ключи должны быть уникальными (в пределах одного словаря). Пара фигурных скобок создает пустой словарь: `{}`. Размещение внутри скобок списка пар ключ:значение, разделенных запятыми, добавляет начальные пары ключ:значение в словарь; так же словари отображаются при выводе.444445Основные операции со словарём – сохранение значения по ключу и извлечение значения по ключу. Также можно удалить пару ключ:значение с помощью `del`. Если сохранить значение по уже существующему ключу, старое значение, связанное с этим ключом, будет забыто. Попытка извлечь значение по несуществующему ключу приводит к ошибке.446447Метод `keys()` объекта-словаря возвращает список всех ключей, используемых в словаре, в произвольном порядке (если нужен отсортированный список, просто примените функцию [`sorted()`](https://python-all.ru/2.7/library/functions.html#sorted) к нему). Чтобы проверить, находится ли ключ в словаре, используйте ключевое слово [`in`](https://python-all.ru/2.7/reference/expressions.html#in).448449Вот небольшой пример использования словаря:450451```python452>>> tel = {'jack': 4098, 'sape': 4139}453>>> tel['guido'] = 4127454>>> tel455{'sape': 4139, 'guido': 4127, 'jack': 4098}456>>> tel['jack']4574098458>>> del tel['sape']459>>> tel['irv'] = 4127460>>> tel461{'guido': 4127, 'irv': 4127, 'jack': 4098}462>>> tel.keys()463['guido', 'irv', 'jack']464>>> 'guido' in tel465True466```467468Конструктор [`dict()`](https://python-all.ru/2.7/library/stdtypes.html#dict) создает словари непосредственно из последовательностей пар ключ-значение:469470```python471>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])472{'sape': 4139, 'jack': 4098, 'guido': 4127}473```474475Кроме того, словарные включения можно использовать для создания словарей из произвольных выражений ключа и значения:476477```python478>>> {x: x**2 for x in (2, 4, 6)}479{2: 4, 4: 16, 6: 36}480```481482Когда ключи являются простыми строками, иногда проще указать пары с помощью именованных аргументов:483484```python485>>> dict(sape=4139, guido=4127, jack=4098)486{'sape': 4139, 'jack': 4098, 'guido': 4127}487```488489## 5.6. Техники циклов490491При переборе последовательности индекс позиции и соответствующее значение можно получить одновременно с помощью функции [`enumerate()`](https://python-all.ru/2.7/library/functions.html#enumerate).492493```python494>>> for i, v in enumerate(['tic', 'tac', 'toe']):495... print i, v496...4970 tic4981 tac4992 toe500```501502Чтобы перебрать две или более последовательности одновременно, элементы можно объединить в пары с помощью функции [`zip()`](https://python-all.ru/2.7/library/functions.html#zip).503504```python505>>> questions = ['name', 'quest', 'favorite color']506>>> answers = ['lancelot', 'the holy grail', 'blue']507>>> for q, a in zip(questions, answers):508... print 'What is your {0}? It is {1}.'.format(q, a)509...510What is your name? It is lancelot.511What is your quest? It is the holy grail.512What is your favorite color? It is blue.513```514515Чтобы перебрать последовательность в обратном порядке, сначала укажите последовательность в прямом направлении, а затем вызовите функцию [`reversed()`](https://python-all.ru/2.7/library/functions.html#reversed).516517```python518>>> for i in reversed(xrange(1,10,2)):519... print i520...52195227523552435251526```527528Чтобы перебрать последовательность в отсортированном порядке, используйте функцию [`sorted()`](https://python-all.ru/2.7/library/functions.html#sorted), которая возвращает новый отсортированный список, оставляя исходный без изменений.529530```python531>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']532>>> for f in sorted(set(basket)):533... print f534...535apple536banana537orange538pear539```540541При переборе словарей ключ и соответствующее значение можно получить одновременно с помощью метода `iteritems()`.542543```python544>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}545>>> for k, v in knights.iteritems():546... print k, v547...548gallahad the pure549robin the brave550```551552Иногда возникает соблазн изменить список во время его перебора; однако часто проще и безопаснее создать новый список.553554```python555>>> import math556>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]557>>> filtered_data = []558>>> for value in raw_data:559... if not math.isnan(value):560... filtered_data.append(value)561...562>>> filtered_data563[56.2, 51.7, 55.3, 52.5, 47.8]564```565566## 5.7. Подробнее об условиях567568Условия, используемые в операторах `while` и `if`, могут содержать любые операторы, а не только сравнения.569570Операторы сравнения `in` и `not in` проверяют, встречается ли значение (или не встречается) в последовательности. Операторы `is` и `is not` сравнивают, являются ли два объекта действительно одним и тем же объектом; это важно только для изменяемых объектов, таких как списки. Все операторы сравнения имеют одинаковый приоритет, который ниже приоритета всех числовых операторов.571572Сравнения можно объединять в цепочку. Например, `a < b == c` проверяет, меньше ли `a` `b` и равно ли `b` `c`.573574Сравнения можно комбинировать с помощью логических операторов `and` и `or`, а результат сравнения (или любого другого логического выражения) можно инвертировать с помощью `not`. Они имеют более низкий приоритет, чем операторы сравнения; среди них `not` имеет наивысший приоритет, а `or` – наинизший, так что `A and not B or C` эквивалентно `(A and (not B)) or C`. Как всегда, круглые скобки можно использовать для явного указания порядка вычислений.575576The Boolean operators `and` and `or` are so-called *short-circuit* operators: their arguments are evaluated from left to right, and evaluation stops as soon as the outcome is determined. For example, if `A` and `C` are true but `B` is false, `A and B and C` does not evaluate the expression `C`. When used as a general value and not as a Boolean, the return value of a short-circuit operator is the last evaluated argument.577578Результат сравнения или другого логического выражения можно присвоить переменной. Например,579580```python581>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'582>>> non_null = string1 or string2 or string3583>>> non_null584'Trondheim'585```586587В Python, в отличие от C, присваивание не может использоваться внутри выражений. Программисты на C могут ворчать по этому поводу, но это позволяет избежать распространённого класса проблем, встречающихся в программах на C: ввод `=` в выражении, когда подразумевался `==`.588589## 5.8. Сравнение последовательностей и других типов590591Объекты-последовательности можно сравнивать с другими объектами того же типа последовательности. Сравнение использует *лексикографический* порядок: сначала сравниваются первые два элемента, и если они различаются, это определяет результат сравнения; если они равны, сравниваются следующие два элемента, и так далее, пока одна из последовательностей не закончится. Если два сравниваемых элемента сами являются последовательностями того же типа, лексикографическое сравнение выполняется рекурсивно. Если все элементы двух последовательностей равны, последовательности считаются равными. Если одна последовательность является начальной подпоследовательностью другой, более короткая последовательность считается меньшей. Лексикографический порядок для строк использует порядок ASCII для отдельных символов. Несколько примеров сравнения последовательностей одного типа:592593```python594(1, 2, 3) < (1, 2, 4)595[1, 2, 3] < [1, 2, 4]596'ABC' < 'C' < 'Pascal' < 'Python'597(1, 2, 3, 4) < (1, 2, 4)598(1, 2) < (1, 2, -1)599(1, 2, 3) == (1.0, 2.0, 3.0)600(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)601```602603Обратите внимание, что сравнение объектов разных типов допустимо. Результат детерминирован, но произволен: типы упорядочиваются по их имени. Таким образом, список всегда меньше строки, строка всегда меньше кортежа и т.д. [1](https://python-all.ru/2.7/tutorial/datastructures.html#id2) Смешанные числовые типы сравниваются по их числовому значению, так что 0 равно 0.0 и т.д.604605Сноски606607**[1](https://python-all.ru/2.7/tutorial/datastructures.html#id1)**608609Не следует полагаться на правила сравнения объектов разных типов; они могут измениться в будущей версии языка.610