М. Лутц - Изучаем Python (4-е издание)- 2011 (1126907), страница 70
Текст из файла (страница 70)
В частности, в версии 3.0 словари:•• Поддерживают новые выражения генераторов словарей, близко напоминающие генераторы списков и множеств.•• Методы D.keys, D.values и D.items возвращают итерируемые представлениявместо списков.•• Вследствие особенности, описанной в предыдущем пункте, требуют по иному выполнять обход ключей в отсортированном порядке.•• Больше не поддерживают возможность непосредственного сравниваниямежду собой – теперь сравнивание должно выполняться вручную.•• Больше не поддерживают метод D.has_key – вместо него следует использовать оператор in проверки на вхождение.Давайте посмотрим, что нового появилось в словарях с выходом версии 3.0.Генераторы словарейКак отмечалось в конце предыдущего раздела, в версии 3.0 появилась возможность создавать словари с помощью генераторов словарей. Как и генераторымножеств, с которыми мы встречались в главе 5, генераторы словарей доступны только в версии 3.0 (они недоступны в версии 2.6).
Подобно давно существующим генераторам списков, с которыми мы встречались в главе 4 и ранеев этой главе, генераторы словарей выполняют цикл, отбирают пары ключ/значение в каждой итерации и заполняют ими новый словарь. Значения, получаемые в ходе итераций, доступны в виде переменной цикла.Например, одним из стандартных способов динамической инициализациисловаря в версиях 2.6 и 3.0 является использование функции zip для объединения ключей и значений с последующей передачей результата функции dict.Как мы узнаем в главе 13, функция zip позволяет единственным вызовом создать словарь из списков ключей и значений.
Если множество ключей и значений заранее не известно, вы всегда можете поместить их в списки в процессевычислений и затем объединить их воедино:>>> list(zip([‘a’, ‘b’, ‘c’], [1, 2, 3])) # Объединить ключи и значения[(‘a’, 1), (‘b’, 2), (‘c’, 3)]>>> D = dict(zip([‘a’, ‘b’, ‘c’], [1, 2, 3]))>>> D{‘a’: 1, ‘c’: 3, ‘b’: 2}# Создать словарь из результата# вызова функции zipВ Python 3.0 того же эффекта можно добиться с помощью генератора словарей.В следующем примере демонстрируется создание нового словаря из пар ключ/значение, которые извлекаются из результата вызова функции zip (это выражение читается практически точно так же, хотя и выглядит немного сложнее):Словари в действии277C:\misc> c:\python30\python# Использование генератора словарей>>> D = {k: v for (k, v) in zip([‘a’, ‘b’, ‘c’], [1, 2, 3])}>>> D{‘a’: 1, ‘c’: 3, ‘b’: 2}Генераторы словарей выглядят менее компактными, но они гораздо более универсальны, чем можно было бы предположить, исходя из этого примера, – мыможем использовать их для отображения единственной последовательностизначений в словари, вычисляя ключи с помощью выражений, как обычныезначения:>>> D = {x: x ** 2 for x in [1, 2, 3, 4]} # Или: range(1, 5)>>> D{1: 1, 2: 4, 3: 9, 4: 16}>>> D = {c: c * 4 for c in ‘SPAM’}# Цикл через итерируемый объект>>> D{‘A’: ‘AAAA’, ‘P’: ‘PPPP’, ‘S’: ‘SSSS’, ‘M’: ‘MMMM’}>>> D = {c.lower(): c + ‘!’ for c in [‘SPAM’, ‘EGGS’, ‘HAM’]}>>> D{‘eggs’: ‘EGGS!’, ‘ham’: ‘HAM!’, ‘spam’: ‘SPAM!’}Генераторы словарей удобно использовать для инициализации словарей изсписков ключей, почти так же, как это делает метод fromkeys, с которым мывстречались в предыдущем разделе:>>> D = dict.fromkeys([‘a’, ‘b’, ‘c’], 0) # Инициализация списком ключей>>> D{‘a’: 0, ‘c’: 0, ‘b’: 0}>>> D = {k:0 for k in [‘a’, ‘b’, ‘c’]} # То же самое, но с помощью>>> D# генератора словаря{‘a’: 0, ‘c’: 0, ‘b’: 0}>>> D = dict.fromkeys(‘spam’)# Из другого итерируемого объекта,>>> D# используются значения по умолчанию{‘a’: None, ‘p’: None, ‘s’: None, ‘m’: None}>>> D = {k: None for k in ‘spam’}>>> D{‘a’: None, ‘p’: None, ‘s’: None, ‘m’: None}Подобно родственным инструментам, генераторы словарей поддерживают дополнительные возможности, которые не были продемонстрированы здесь,включая вложенные циклы и условные инструкции if.
К сожалению, чтобыполностью понять все возможности генераторов словарей, нам необходимопознакомиться поближе с концепцией и инструкциями итераций в языкеPython, – но у нас пока недостаточно знаний, чтобы обсуждать эту тему. Мыпознакомимся поближе со всеми разновидностями генераторов (списков, множеств и словарей) в главах 14 и 20, поэтому отложим пока обсуждение деталей.Кроме того, в главе 13 мы поближе познакомимся со встроенной функцией zip,которую использовали в этом разделе, когда будем исследовать циклы for.Представления словарейВ версии 3.0 методы словарей keys, values и items возвращают объекты представлений, тогда как в версии 2.6 они возвращают списки.
Объекты представ-278Глава 8. Списки и словарилений – это итерируемые объекты, то есть объекты, которые вместо всего списка значений возвращают по одному значению за одно обращение. Кроме того,что они являются итерируемыми объектами, представления словарей такжесохраняют оригинальный порядок следования компонентов словаря, отражают результаты операций, которые выполняются над словарем, и поддерживают операции над множествами. С другой стороны, они не являются спискамии не поддерживают такие операции, как обращение к элементам по индексамили метод sort списков, а также не отображают значения своих элементов привыводе.Понятие итерируемого объекта более формально будет рассматриваться в главе 14, а пока нам достаточно будет знать, что результаты этих трех методовнеобходимо обертывать вызовом встроенной функции list, – если появитсянеобходимость применить операции над списками или отобразить значенияэлементов:>>> D = dict(a=1, b=2, c=3)>>> D{‘a’: 1, ‘c’: 3, ‘b’: 2}>>> K = D.keys() # В версии 3.0 создаст объект представления, а не список>>> K<dict_keys object at 0x026D83C0>>>> list(K)[‘a’, ‘c’, ‘b’]# Принудительное создание списка в версии 3.0>>> V = D.values() # То же относится к представлениям значений и элементов>>> V<dict_values object at 0x026D8260>>>> list(V)[1, 3, 2]>>> list(D.items())[(‘a’, 1), (‘c’, 3), (‘b’, 2)]>>> K[0]# Ошибка при попытке выполнить операцию над спискомTypeError: ‘dict_keys’ object does not support indexing>>> list(K)[0]‘a’Кроме случаев отображения результатов в интерактивной оболочке, вы едва либудете обращать внимание на эту особенность, потому что конструкции обхода элементов в цикле в языке Python автоматически заставляют итерируемыеобъекты возвращать по одному результату в каждой итерации:>>> for k in D.keys(): print(k) # Работа с итераторами в циклах...# выполняется автоматическиacbКроме того, в версии 3.0 словари по-прежнему остаются итерируемыми объектами, которые последовательно возвращают ключи, как и в версии 2.6, – чтоисключает необходимость вызывать метод keys:>>> for key in D: print(key) # В итерациях по-прежнему не обязательно...# вызывать метод keys()279Словари в действииacbВ отличие от списков, возвращаемых в виде результатов в версии 2.��������X�������, представления словарей в версии 3.0 способны динамически отражать все последующие изменения в словарях, выполненные уже после создания объекта отображения:>>> D = {‘a’:1, ‘b’:2, ‘c’:3}>>> D{‘a’: 1, ‘c’: 3, ‘b’: 2}>>> K = D.keys()>>> V = D.values()>>> list(K)# Представления сохраняют оригинальный[‘a’, ‘c’, ‘b’]# порядок следования ключей в словаре>>> list(V)[1, 3, 2]>>> del D[‘b’]>>> D{‘a’: 1, ‘c’: 3}# Изменяет словарь непосредственно>>> list(K)[‘a’, ‘c’]>>> list(V)[1, 3]# Изменения в словаре отражаются на объектах представлений# Но это не так в версии 2.X!Представления словарей и множестваКроме того, в отличие от списков результатов, возвращаемых в версии 2.X,объекты представлений в версии 3.0, возвращаемые методом keys, похожи намножества и поддерживают операции над множествами, такие как пересечение и объединение.
Объекты представлений, возвращаемые методом values,такой особенностью не обладают, потому что они не являются уникальными,тогда как объекты представлений, возвращаемые методом items, такой особенностью обладают, если пары (key, value) являются уникальными и хешируемыми. Учитывая, что множества достаточно сильно похожи на словари, ключикоторых не имеют значений (и даже литералы множеств в версии 3.0 заключаются в фигурные скобки, как словари), это обстоятельство выглядит вполне логичным. Подобно ключам словарей, элементы множеств неупорядочены,уникальны и относятся к разряду неизменяемых объектов.Ниже наглядно показано, как интерпретируются списки ключей, когда онииспользуются в операциях над множествами.