ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов
Скачать 7.92 Mb.
|
>>> itertools.tee(arr, 3) ( >>> list(itertools.tee(arr)[0]) [1, 2, 3] >>> list(itertools.tee(arr)[1]) [1, 2, 3] ГЛ А В А 9 Словари Словари — это наборы объектов, доступ к которым осуществляется не по индексу, а по ключу. В качестве ключа можно указать неизменяемый объект, например: число, строку или кортеж. Элементы словаря могут содержать объекты произвольного типа данных и иметь неограниченную степень вложенности. Следует также заметить, что элементы в сло- варях располагаются в произвольном порядке. Чтобы получить элемент, необходимо ука- зать ключ, который использовался при сохранении значения. Словари относятся к отображениям, а не к последовательностям. По этой причине функции, предназначенные для работы с последовательностями, а также операции извлечения среза, конкатенации, повторения и др., к словарям не применимы. Равно как и списки, словари относятся к изменяемым типам данных. Иными словами, мы можем не только получить значение по ключу, но и изменить его. 9.1. Создание словаря Создать словарь можно следующими способами: с помощью функции dict() . Форматы функции: dict(<Ключ1>=<Значение1>[, ..., <КлючN>=<ЗначениеN>]) dict(<Словарь>) dict(<Список кортежей с двумя элементами (Ключ, Значение)>) dict(<Список списков с двумя элементами [Ключ, Значение]>) Если параметры не указаны, создается пустой словарь: >>> d = dict(); d # Создаем пустой словарь {} >>> d = dict(a=1, b=2); d {'a': 1, 'b': 2} >>> d = dict({"a": 1, "b": 2}); d # Словарь {'a': 1, 'b': 2} >>> d = dict([("a", 1), ("b", 2)]); d # Список кортежей {'a': 1, 'b': 2} >>> d = dict([["a", 1], ["b", 2]]); d # Список списков {'a': 1, 'b': 2} 176 Часть I. Основы языка Python Объединить два списка в список кортежей позволяет функция zip() : >>> k = ["a", "b"] # Список с ключами >>> v = [1, 2] # Список со значениями >>> list(zip(k, v)) # Создание списка кортежей [('a', 1), ('b', 2)] >>> d = dict(zip(k, v)); d # Создание словаря {'a': 1, 'b': 2} указав все элементы словаря внутри фигурных скобок — это наиболее часто используе- мый способ создания словаря. Между ключом и значением ставится двоеточие, а пары «ключ/значение» записываются через запятую: >>> d = {}; d # Создание пустого словаря {} >>> d = { "a": 1, "b": 2 }; d {'a': 1, 'b': 2} заполнив словарь поэлементно. В этом случае ключ указывается внутри квадратных скобок: >>> d = {} # Создаем пустой словарь >>> d["a"] = 1 # Добавляем элемент1 (ключ "a") >>> d["b"] = 2 # Добавляем элемент2 (ключ "b") >>> d {'a': 1, 'b': 2} с помощью метода dict.fromkeys(<Последовательность>[, <Значение>]) . Метод создает новый словарь, ключами которого станут элементы последовательности, переданной первым параметром, а их значениями — величина, переданная вторым параметром. Если второй параметр не указан, элементы словаря получат в качестве значения None : >>> d = dict.fromkeys(["a", "b", "c"]) >>> d {'a': None, 'c': None, 'b': None} >>> d = dict.fromkeys(["a", "b", "c"], 0) # Указан список >>> d {'a': 0, 'c': 0, 'b': 0} >>> d = dict.fromkeys(("a", "b", "c"), 0) # Указан кортеж >>> d {'a': 0, 'c': 0, 'b': 0} При создании словаря в переменной сохраняется ссылка на объект, а не сам объект. Это обязательно следует учитывать при групповом присваивании. Групповое присваивание можно использовать для чисел и строк, но для списков и словарей этого делать нельзя. Рас- смотрим пример: >>> d1 = d2 = { "a": 1, "b": 2 } # Якобы создали два объекта >>> d2["b"] = 10 >>> d1, d2 # Изменилось значение в двух переменных !!! ({'a': 1, 'b': 10}, {'a': 1, 'b': 10}) Сразу видно, что изменение значения в переменной d2 привело также к изменению значе- ния в переменной d1 , т. е. обе переменные ссылаются на один и тот же объект. Чтобы полу- чить два объекта, необходимо производить раздельное присваивание: Глава 9. Словари 177 >>> d1, d2 = { "a": 1, "b": 2 }, { "a": 1, "b": 2 } >>> d2["b"] = 10 >>> d1, d2 ({'a': 1, 'b': 2}, {'a': 1, 'b': 10}) Создать поверхностную копию словаря позволяет функция dict() : >>> d1 = { "a": 1, "b": 2 } # Создаем словарь >>> d2 = dict(d1) # Создаем поверхностную копию >>> d1 is d2 # Оператор показывает, что это разные объекты False >>> d2["b"] = 10 >>> d1, d2 # Изменилось только значение в переменной d2 ({'a': 1, 'b': 2}, {'a': 1, 'b': 10}) Также можно воспользоваться методом copy() : >>> d1 = { "a": 1, "b": 2 } # Создаем словарь >>> d2 = d1.copy() # Создаем поверхностную копию >>> d1 is d2 # Оператор показывает, что это разные объекты False >>> d2["b"] = 10 >>> d1, d2 # Изменилось только значение в переменной d2 ({'a': 1, 'b': 2}, {'a': 1, 'b': 10}) Чтобы создать полную копию словаря, следует воспользоваться функцией deepcopy() из модуля copy : >>> d1 = { "a": 1, "b": [20, 30, 40] } >>> d2 = dict(d1) # Создаем поверхностную копию >>> d2["b"][0] = "test" >>> d1, d2 # Изменились значения в двух переменных!!! ({'a': 1, 'b': ['test', 30, 40]}, {'a': 1, 'b': ['test', 30, 40]}) >>> import copy >>> d3 = copy.deepcopy(d1) # Создаем полную копию >>> d3["b"][1] = 800 >>> d1, d3 # Изменилось значение только в переменной d3 ({'a': 1, 'b': ['test', 30, 40]}, {'a': 1, 'b': ['test', 800, 40]}) 9.2. Операции над словарями Обращение к элементам словаря осуществляется с помощью квадратных скобок, в которых указывается ключ. В качестве ключа можно указать неизменяемый объект, например: чис- ло, строку или кортеж. Выведем все элементы словаря: >>> d = { 1: "int", "a": "str", (1, 2): "tuple" } >>> d[1], d["a"], d[(1, 2)] ('int', 'str', 'tuple') Если элемент, соответствующий указанному ключу, отсутствует в словаре, возбуждается исключение KeyError : 178 Часть I. Основы языка Python >>> d = { "a": 1, "b": 2 } >>> d["c"] # Обращение к несуществующему элементу Traceback (most recent call last): File " ", line 1, in KeyError: 'c' Проверить существование ключа в словаре можно с помощью оператора in . Если ключ найден, возвращается значение True , в противном случае — False : >>> d = { "a": 1, "b": 2 } >>> "a" in d # Ключ существует True >>> "c" in d # Ключ не существует False Проверить, отсутствует ли какой-либо ключ в словаре, позволит оператор not in . Если ключ отсутствует, возвращается True , иначе — False : >>> d = { "a": 1, "b": 2 } >>> "c" not in d # Ключ не существует True >>> "a" not in d # Ключ существует False Метод get(<Ключ>[, <Значение по умолчанию>]) позволяет избежать возбуждения исклю- чения KeyError при отсутствии в словаре указанного ключа. Если ключ присутствует в сло- варе, метод возвращает значение, соответствующее этому ключу. Если ключ отсутствует, возвращается None или значение, указанное во втором параметре: >>> d = { "a": 1, "b": 2 } >>> d.get("a"), d.get("c"), d.get("c", 800) (1, None, 800) Кроме того, можно воспользоваться методом setdefault(<Ключ>[, <Значение по умолча- нию>]) . Если ключ присутствует в словаре, метод возвращает значение, соответствующее этому ключу. Если ключ отсутствует, в словаре создается новый элемент со значением, ука- занным во втором параметре. Если второй параметр не указан, значением нового элемента будет None : >>> d = { "a": 1, "b": 2 } >>> d.setdefault("a"), d.setdefault("c"), d.setdefault("d", 0) (1, None, 0) >>> d {'a': 1, 'c': None, 'b': 2, 'd': 0} Так как словари относятся к изменяемым типам данных, мы можем изменить элемент по ключу. Если элемент с указанным ключом отсутствует в словаре, он будет создан: >>> d = { "a": 1, "b": 2 } >>> d["a"] = 800 # Изменение элемента по ключу >>> d["c"] = "string" # Будет добавлен новый элемент >>> d {'a': 800, 'c': 'string', 'b': 2} Глава 9. Словари 179 Получить количество ключей в словаре позволяет функция len() : >>> d = { "a": 1, "b": 2 } >>> len(d) # Получаем количество ключей в словаре 2 Удалить элемент из словаря можно с помощью оператора del : >>> d = { "a": 1, "b": 2 } >>> del d["b"]; d # Удаляем элемент с ключом "b" и выводим словарь {'a': 1} 9.3. Перебор элементов словаря Перебрать все элементы словаря можно с помощью цикла for , хотя словари и не являются последовательностями. Для примера выведем элементы словаря двумя способами. Первый способ использует метод keys() , возвращающий объект с ключами словаря. Во втором слу- чае мы просто указываем словарь в качестве параметра. На каждой итерации цикла будет возвращаться ключ, с помощью которого внутри цикла можно получить значение, соответ- ствующее этому ключу (листинг 9.1). Листинг 9.1. Перебор элементов словаря d = {"x": 1, "y": 2, "z": 3} for key in d.keys(): # Использование метода keys() print("({0} => {1})".format(key, d[key]), end=" ") # Выведет: (y => 2) (x => 1) (z => 3) print() # Вставляем символ перевода строки for key in d: # Словари также поддерживают итерации print("({0} => {1})".format(key, d[key]), end=" ") # Выведет: (y => 2) (x => 1) (z => 3) Поскольку словари являются неупорядоченными структурами, элементы словаря выводятся в произвольном порядке. Чтобы вывести элементы с сортировкой по ключам, следует полу- чить список ключей, а затем воспользоваться методом sort() (листинг 9.2). Листинг 9.2. Упорядоченный вывод элементов словаря с помощью метода sort() d = {"x": 1, "y": 2, "z": 3} k = list(d.keys()) # Получаем список ключей k.sort() # Сортируем список ключей for key in k: print("({0} => {1})".format(key, d[key]), end=" ") # Выведет: (x => 1) (y => 2) (z => 3) Для сортировки ключей вместо метода sort() можно воспользоваться функцией sorted() (листинг 9.3). 180 Часть I. Основы языка Python Листинг 9.3. Упорядоченный вывод элементов словаря с помощью функции sorted() d = {"x": 1, "y": 2, "z": 3} for key in sorted(d.keys()): print("({0} => {1})".format(key, d[key]), end=" ") # Выведет: (x => 1) (y => 2) (z => 3) Так как на каждой итерации возвращается ключ словаря, функции sorted() можно сразу передать объект словаря, а не результат выполнения метода keys() (листинг 9.4). Листинг 9.4. Упорядоченный вывод элементов словаря с помощью функции sorted() d = {"x": 1, "y": 2, "z": 3} for key in sorted(d): print("({0} => {1})".format(key, d[key]), end=" ") # Выведет: (x => 1) (y => 2) (z => 3) 9.4. Методы для работы со словарями Для работы со словарями предназначены следующие методы: keys() — возвращает объект dict_keys , содержащий все ключи словаря. Этот объект поддерживает итерации, а также операции над множествами: >>> d1, d2 = { "a": 1, "b": 2 }, { "a": 3, "c": 4, "d": 5 } >>> d1.keys(), d2.keys() # Получаем объект dict_keys (dict_keys(['a', 'b']), dict_keys(['a', 'c', 'd'])) >>> list(d1.keys()), list(d2.keys()) # Получаем список ключей (['a', 'b'], ['a', 'c', 'd']) >>> for k in d1.keys(): print(k, end=" ") a b >>> d1.keys() | d2.keys() # Объединение {'a', 'c', 'b', 'd'} >>> d1.keys() — d2.keys() # Разница {'b'} >>> d2.keys() — d1.keys() # Разница {'c', 'd'} >>> d1.keys() & d2.keys() # Одинаковые ключи {'a'} >>> d1.keys() ^ d2.keys() # Уникальные ключи {'c', 'b', 'd'} values() — возвращает объект dict_values , содержащий все значения словаря. Этот объект поддерживает итерации: >>> d = { "a": 1, "b": 2 } >>> d.values() # Получаем объект dict_values dict_values([1, 2]) >>> list(d.values()) # Получаем список значений [1, 2] Глава 9. Словари 181 >>> [ v for v in d.values() ] [1, 2] items() — возвращает объект dict_items , содержащий все ключи и значения в виде кор- тежей. Этот объект поддерживает итерации: >>> d = { "a": 1, "b": 2 } >>> d.items() # Получаем объект dict_items dict_items([('a', 1), ('b', 2)]) >>> list(d.items()) # Получаем список кортежей [('a', 1), ('b', 2)] <Ключ> in <Словарь> — проверяет существование указанного ключа в словаре. Если ключ найден, возвращается значение True , в противном случае — False : >>> d = { "a": 1, "b": 2 } >>> "a" in d # Ключ существует True >>> "c" in d # Ключ не существует False <Ключ> not in <Словарь> — проверяет отсутствие указанного ключа в словаре. Если такового ключа нет, возвращается значение True , в противном случае — False : >>> d = { "a": 1, "b": 2 } >>> "c" not in d # Ключ не существует True >>> "a" not in d # Ключ существует False get(<Ключ>[, <Значение по умолчанию>]) — если ключ присутствует в словаре, метод возвращает значение, соответствующее этому ключу. Если ключ отсутствует, возвраща- ется None или значение, указанное во втором параметре: >>> d = { "a": 1, "b": 2 } >>> d.get("a"), d.get("c"), d.get("c", 800) (1, None, 800) setdefault(<Ключ>[, <Значение по умолчанию>]) — если ключ присутствует в словаре, метод возвращает значение, соответствующее этому ключу. Если ключ отсутствует, в словаре создается новый элемент со значением, указанным во втором параметре. Если второй параметр не указан, значением нового элемента будет None : >>> d = { "a": 1, "b": 2 } >>> d.setdefault("a"),d.setdefault("c"),d.setdefault("d", 0) (1, None, 0) >>> d {'a': 1, 'c': None, 'b': 2, 'd': 0} pop(<Ключ>[, <Значение по умолчанию>]) — удаляет элемент с указанным ключом и возвращает его значение. Если ключ отсутствует, возвращается значение из второго параметра. Если ключ отсутствует и второй параметр не указан, возбуждается исключе- ние KeyError : >>> d = { "a": 1, "b": 2, "c": 3 } >>> d.pop("a"), d.pop("n", 0) (1, 0) 182 Часть I. Основы языка Python >>> d.pop("n") # Ключ отсутствует и нет второго параметра Traceback (most recent call last): File " ", line 1, in KeyError: 'n' >>> d {'c': 3, 'b': 2} popitem() — удаляет произвольный элемент и возвращает кортеж из ключа и значения. Если словарь пустой, возбуждается исключение KeyError : >>> d = { "a": 1, "b": 2 } >>> d.popitem() # Удаляем произвольный элемент ('a', 1) >>> d.popitem() # Удаляем произвольный элемент ('b', 2) >>> d.popitem() # Словарь пустой. Возбуждается исключение Traceback (most recent call last): File " ", line 1, in KeyError: 'popitem(): dictionary is empty' clear() — удаляет все элементы словаря. Метод ничего не возвращает в качестве значе- ния: >>> d = { "a": 1, "b": 2 } >>> d.clear() # Удаляем все элементы >>> d # Словарь теперь пустой {} update() — добавляет элементы в словарь. Метод изменяет текущий словарь и ничего не возвращает. Форматы метода: update(<Ключ1>=<Значение1>[, ..., <КлючN>=<ЗначениеN>]) update(<Словарь>) update(<Список кортежей с двумя элементами>) update(<Список списков с двумя элементами>) Если элемент с указанным ключом уже присутствует в словаре, то его значение будет перезаписано. Примеры: >>> d = { "a": 1, "b": 2 } >>> d.update(c=3, d=4) >>> d {'a': 1, 'c': 3, 'b': 2, 'd': 4} >>> d.update({"c": 10, "d": 20}) # Словарь >>> d # Значения элементов перезаписаны {'a': 1, 'c': 10, 'b': 2, 'd': 20} >>> d.update([("d", 80), ("e", 6)]) # Список кортежей >>> d {'a': 1, 'c': 10, 'b': 2, 'e': 6, 'd': 80} Глава 9. Словари 183 >>> d.update([["a", "str"], ["i", "t"]]) # Список списков >>> d {'a': 'str', 'c': 10, 'b': 2, 'e': 6, 'd': 80, 'i': 't'} copy() — создает поверхностную копию словаря: >>> d1 = { "a": 1, "b": [10, 20] } >>> d2 = d1.copy() # Создаем поверхностную копию >>> d1 is d2 # Это разные объекты False >>> d2["a"] = 800 # Изменяем значение >>> d1, d2 # Изменилось значение только в d2 ({'a': 1, 'b': [10, 20]}, {'a': 800, 'b': [10, 20]}) >>> d2["b"][0] = "new" # Изменяем значение вложенного списка >>> d1, d2 # Изменились значения и в d1, и в d2!!! ({'a': 1, 'b': ['new', 20]}, {'a': 800, 'b': ['new', 20]}) Чтобы создать полную копию словаря, следует воспользоваться функцией deepcopy() из модуля copy 9.5. Генераторы словарей Помимо генераторов списков, язык Python 3 поддерживает генераторы словарей. Синтаксис генераторов словарей похож на синтаксис генераторов списков, но имеет два различия: выражение заключается в фигурные скобки, а не в квадратные; внутри выражения перед циклом for указываются два значения через двоеточие, а не одно. Значение, расположенное слева от двоеточия, становится ключом, а значение, рас- положенное справа от двоеточия, — значением элемента. Пример: >>> keys = ["a", "b"] # Список с ключами >>> values = [1, 2] # Список со значениями >>> {k: v for (k, v) in zip(keys, values)} {'a': 1, 'b': 2} >>> {k: 0 for k in keys} {'a': 0, 'b': 0} Генераторы словарей могут иметь сложную структуру — например, состоять из нескольких вложенных циклов for и (или) содержать оператор ветвления if после цикла. Создадим из исходного словаря новый словарь, содержащий только элементы с четными значениями: >>> d = { "a": 1, "b": 2, "c": 3, "d": 4 } >>> {k: v for (k, v) in d.items() if v % 2 == 0} {'b': 2, 'd': 4} |