Python的字典
一、基本介紹
在Python中,如果沒有列表和字典是不可想象的。字典及其強(qiáng)有力的實(shí)現(xiàn)是使Python如此有效和出眾的重要原因。本文將展示字典及其使用方法。
字典和列表之間可以相互轉(zhuǎn)換,但字典和列表的不同之處在哪里?首先列表是有序的,而字典是無序的,但核心的不同在于字典是通過鍵(key)來訪問,而列表是通過位置訪問。更進(jìn)一步講,字典是一種抽象數(shù)據(jù)類型的實(shí)現(xiàn)。字典的每一個(gè)鍵都與一個(gè)值相關(guān)聯(lián)。值可以是任意的Python數(shù)據(jù)類型。此外,字典不支持像位置索引、切片等序列操作方法。
二、字典實(shí)例
第一個(gè)例子是關(guān)于美國和加拿大的幾個(gè)大城市人口的,首先創(chuàng)建一個(gè)名為city的字典,字典中包含一些城市以及這些城市包含的人口數(shù)量:
>>> city = {"New York City":8175133, "Los Angeles": 3792621, "Washington":632323, "Chicago": 2695598, "Toronto":2615060, "Montreal":11854442, "Ottawa":883391, "Boston":62600}如果我們想得到某個(gè)城市的人口數(shù)量,我們可以直接用城市的名稱進(jìn)行查詢:
>>> city["New York City"] 8175133 >>> city["Toronto"] 2615060 >>> city["Boston"] 62600如果我們用city中不存在的城市名稱作為key訪問,則會(huì)報(bào)錯(cuò)。
>>> city["Detroit"] Traceback (most recent call last):File "<stdin>", line 1, in KeyError: 'Detroit'如果你回看下上面定義的字典city,你可能會(huì)覺得字典中的元素是有序的,例如,第一個(gè)是”New York City”, 第二個(gè)是 “Los Angeles” 等等,但事實(shí)上字典是無序的。我們再輸出查看下city,得到的順序可能與原始順序是不一樣的。
>>> city {'Toronto': 2615060, 'Ottawa': 883391, 'Los Angeles': 3792621, 'Chicago': 2695598, 'New York City': 8175133, 'Boston': 62600, 'Washington': 632323, 'Montreal': 11854442}因此,字典不能像列表一樣通過一個(gè)數(shù)字索引來訪問元素。
>>> city[0] Traceback (most recent call last):File "<stdin>", line 1, in KeyError: 0 >>>向字典添加元素很簡單,直接賦值即可。
>>> city["Halifax"] = 390096 >>> city {'Toronto': 2615060, 'Ottawa': 883391, 'Los Angeles': 3792621, 'Chicago': 2695598, 'New York City': 8175133, 'Halifax': 390096, 'Boston': 62600, 'Washington': 632323, 'Montreal': 11854442}因此,通過往一個(gè)空字典中遞增式添加元素從而獲得所需字典的方式是可行的。前面還沒有提到如何創(chuàng)建一個(gè)空字典。如下是創(chuàng)建一個(gè)名字為city的空字典的方式:
>>> city = {} >>> city {}下一個(gè)例子是一個(gè)簡單的英德字典:
en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"} print(en_de) print(en_de["red"])再定義一個(gè)德法字典:
de_fr = {"rot" : "rouge", "grün" : "vert", "blau" : "bleu", "gelb":"jaune"}現(xiàn)在,它可以從英語翻譯成法語了。盡管我們沒有一個(gè)英法字典,但是通過de_fr[en_de[“red”]] 我們能夠得到”red”的法文翻譯:”rouge”。
en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"} print(en_de) print(en_de["red"]) de_fr = {"rot" : "rouge", "grün" : "vert", "blau" : "bleu", "gelb":"jaune"} print("The French word for red is: " + de_fr[en_de["red"]])上面代碼的輸出是:
{'blue': 'blau', 'green': 'grün', 'yellow': 'gelb', 'red': 'rot'} rot The French word for red is: rouge在字典中,我們可以用任意類型作為值(value),但是對(duì)鍵(key)是有約束的,只有不可變的類型才能作為鍵。如果用一個(gè)可變類型作為鍵,將會(huì)報(bào)錯(cuò)。下面將一個(gè)列表作為鍵(key),因?yàn)榱斜硎强勺冾愋?#xff0c;所以報(bào)錯(cuò)。
>>> dic = { [1,2,3]:"abc"} Traceback (most recent call last):File "<stdin>", line 1, in <module> TypeError: list objects are unhashable元組是不可變類型,因此可以作為鍵(key):
>>> dic = { (1,2,3):"abc", 3.1415:"abc"} >>> dic {3.1415: 'abc', (1, 2, 3): 'abc'}我們還可以創(chuàng)建一個(gè)包含字典的字典:
en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"} de_fr = {"rot" : "rouge", "grün" : "vert", "blau" : "bleu", "gelb":"jaune"} dictionaries = {"en_de" : en_de, "de_fr" : de_fr } print(dictionaries["de_fr"]["blau"])輸出為:
bleu
三、字典操作
例子:
下面是一個(gè)拉丁字符與其對(duì)應(yīng)摩爾斯碼的字典。
獲取字典中包含的拉丁字符數(shù)量可以調(diào)用len函數(shù):
>>> len(morse) 38這個(gè)字典僅僅包含大寫字母,因此檢查小寫字母”a”是否在字典中將返回False:
>>> "a" in morse False >>> "A" in morse True >>> "a" not in morse Truelist可以像棧(stack)一樣使用pop()函數(shù)彈出一個(gè)元素。但是在字典中,因?yàn)槭菬o序的并且沒有索引,所以pop()函數(shù)有著不一樣的含義。
如果D表示一個(gè)字典,那么D.pop(k)表示從D中移除鍵為k的元素,該操作的返回值是D[k]。
如果鍵k在D中不存在,那么將報(bào)錯(cuò)。
如果我們試圖在上面的字典capitals中找到瑞士(Switzerland)的首都,由于不存在Switzerland,將報(bào)錯(cuò)。為了避免這種錯(cuò)誤,我們可以在pop()函數(shù)中使用第二個(gè)參數(shù)作為缺省值。
>>> capital = capitals.pop("Switzerland", "Bern") >>> print(capital) Bern >>> capital = capitals.pop("France", "Paris") >>> print(capital) Paris >>> capital = capitals.pop("Germany", "München") >>> print(capital) Berlinpopitem()是字典的另一種方法,不需要任何輸入?yún)?shù),將隨機(jī)移除字典中任意一個(gè)元素,返回值為該移除元素的鍵值對(duì)元組 (key,value)。如果是一個(gè)空字典,使用popitem()將報(bào)錯(cuò)。
>>> capitals = {"Springfield":"Illinois", "Augusta":"Maine", "Boston": "Massachusetts", "Lansing":"Michigan", "Albany":"New York", "Olympia":"Washington", "Toronto":"Ontario"} >>> (city, state) = capitals.popitem() >>> (city, state) ('Olympia', 'Washington') >>> print(capitals.popitem()) ('Albany', 'New York') >>> print(capitals.popitem()) ('Boston', 'Massachusetts') >>> print(capitals.popitem()) ('Lansing', 'Michigan') >>> print(capitals.popitem()) ('Toronto', 'Ontario') >>>如果我們訪問字典中不存在的鍵,將得到錯(cuò)誤信息:
>>> locations = {"Toronto" : "Ontario", "Vancouver":"British Columbia"} >>> locations["Ottawa"] Traceback (most recent call last):File "<stdin>", line 1, in <module> KeyError: 'Ottawa'可以通過”in”操作符進(jìn)行事先檢查,從而避免這個(gè)問題。
>>> if "Ottawa" in locations: print(locations["Ottawa"]) ... >>> if "Toronto" in locations: print(locations["Toronto"]) ... Ontario另一種訪問方式是通過get()方法,如果鍵不存在,get()方法不返回錯(cuò)誤,而返回的是None。當(dāng)然也可以設(shè)定一個(gè)鍵(key)不存在時(shí)缺省的返回值。
>>> proj_language = {"proj1":"Python", "proj2":"Perl", "proj3":"Java"} >>> proj_language["proj1"] 'Python' >>> proj_language["proj4"] Traceback (most recent call last):File "<stdin>", line 1, in KeyError: 'proj4' >>> proj_language.get("proj2") 'Perl' >>> proj_language.get("proj4") >>> print(proj_language.get("proj4")) None >>> # setting a default value: >>> proj_language.get("proj4", "Python") 'Python'一個(gè)字典可以使用copy()函數(shù)進(jìn)行復(fù)制:
>>> w = words.copy() >>> words["cat"]="chat" >>> print(w) {'house': 'Haus', 'cat': 'Katze'} >>> print(words) {'house': 'Haus', 'cat': 'chat'}這種拷貝是淺拷貝。如果字典中的值是一個(gè)復(fù)雜的數(shù)據(jù)類型,例如list。
# -*- coding: utf-8 -*-trainings = { "course1":{"title":"Python Training Course for Beginners", "location":"Frankfurt", "trainer":"Steve G. Snake"},"course2":{"title":"Intermediate Python Training","location":"Berlin","trainer":"Ella M. Charming"},"course3":{"title":"Python Text Processing Course","location":"München","trainer":"Monica A. Snowdon"}}trainings2 = trainings.copy()trainings["course2"]["title"] = "Perl Training Course for Beginners" print(trainings2)檢查下輸出,我們能看到改變trainings中course2的title值,trainings2中也發(fā)生了一樣的改變。
{'course2': {'trainer': 'Ella M. Charming', 'title': 'Perl Training Course for Beginners', 'location': 'Berlin'}, 'course3': {'trainer': 'Monica A. Snowdon', 'title': 'Python Text Processing Course', 'location': 'München'}, 'course1': {'trainer': 'Steve G. Snake', 'title': 'Python Training Course for Beginners', 'location': 'Frankfurt'}}如果分配了一個(gè)新值給一個(gè)鍵,看看發(fā)生了什么:
trainings = { "course1":{"title":"Python Training Course for Beginners", "location":"Frankfurt", "trainer":"Steve G. Snake"},"course2":{"title":"Intermediate Python Training","location":"Berlin","trainer":"Ella M. Charming"},"course3":{"title":"Python Text Processing Course","location":"München","trainer":"Monica A. Snowdon"}}trainings2 = trainings.copy()trainings["course2"] = {"title":"Perl Seminar for Beginners","location":"Ulm","trainer":"James D. Morgan"} print(trainings2["course2"])輸出結(jié)果:
{'trainer': 'Ella M. Charming', 'location': 'Berlin', 'title': 'Intermediate Python Training'}檢查下輸出,我們能看到改變trainings中course2的值,trainings2中course2卻沒有改變。如果你想了解這種現(xiàn)象產(chǎn)生的原因,可以回顧下前期文章《Python的淺拷貝和深拷貝》。
字典可以使用clear()函數(shù)清空,執(zhí)行該方法后,字典本身沒有被刪除,而是被置為空字典。
>>> w.clear() >>> print(w) {}能不能將字典合并或歸并在一起呢,答案是肯定的。update()函數(shù)能夠歸并2個(gè)字典,如果存在相同的鍵,那么前一個(gè)字典該鍵下的值將被覆蓋:
>>> knowledge = {"Frank": {"Perl"}, "Monica":{"C","C++"}} >>> knowledge2 = {"Guido":{"Python"}, "Frank":{"Perl", "Python"}} >>> knowledge.update(knowledge2) >>> knowledge {'Frank': {'Python', 'Perl'}, 'Guido': {'Python'}, 'Monica': {'C', 'C++'}}對(duì)于字典的鍵(key)迭代,可以直接使用for循環(huán)和”in”操作符:
>>> d = {"a":123, "b":34, "c":304, "d":99} >>> for key in d: ... print(key) ... b c a d當(dāng)然也可以使用keys()方法,能夠得到相同的效果:
>>> for key in d.keys(): ... print(key) ... b c a dvalues()方法能夠方便的對(duì)值(value)進(jìn)行遍歷。
>>> for value in d.values(): ... print(value) ... 34 304 123 99上面的循環(huán)等價(jià)于如下的循環(huán):
for key in d:print(d[key])但這種沒有第一種效率高。如果你熟悉ipyton的timeit使用方法,你可以測試下這兩種方法的效率差別:
In [5]: %%timeit d = {"a":123, "b":34, "c":304, "d":99} for key in d.keys():x=d[key]...: 1000000 loops, best of 3: 225 ns per loopIn [6]: %%timeit d = {"a":123, "b":34, "c":304, "d":99} for value in d.values():x=value...: 10000000 loops, best of 3: 164 ns per loop四、列表和字典的相互轉(zhuǎn)換
list轉(zhuǎn)換成dict,或者dict轉(zhuǎn)換成list是使用python時(shí)經(jīng)常會(huì)遇到的情況。我們可以通過dict的item()、keys()和values()方法來創(chuàng)建list。
>>> w = {"house":"Haus", "cat":"", "red":"rot"} >>> items_view = w.items() >>> items = list(items_view) >>> items [('house', 'Haus'), ('cat', ''), ('red', 'rot')] >>> >>> keys_view = w.keys() >>> keys = list(keys_view) >>> keys ['house', 'cat', 'red'] >>> >>> values_view = w.values() >>> values = list(values_view) >>> values ['Haus', '', 'rot'] >>> values_view dict_values(['Haus', '', 'rot']) >>> items_view dict_items([('house', 'Haus'), ('cat', ''), ('red', 'rot')]) >>> keys_view dict_keys(['house', 'cat', 'red'])下面再看看列表如何轉(zhuǎn)換成字典。我們有兩個(gè)列表,一個(gè)包含各種美食,一個(gè)是與這些美食相對(duì)應(yīng)的國家。
>>> dishes = ["pizza", "sauerkraut", "paella", "hamburger"] >>> countries = ["Italy", "Germany", "Spain", "USA"]現(xiàn)在我們創(chuàng)建一個(gè)字典,將國家作為key,將該國家對(duì)應(yīng)的美食作為value。首先構(gòu)建一個(gè)新列表,這里我們使用了zip函數(shù)。
>>> country_specialities = list(zip(countries, dishes)) >>> print(country_specialities) [('Italy', 'pizza'), ('Germany', 'sauerkraut'), ('Spain', 'paella'), ('USA', 'hamburger')]然后通過dict()方法將列表轉(zhuǎn)換成字典。
>>> country_specialities_dict = dict(country_specialities) >>> print(country_specialities_dict) {'Germany': 'sauerkraut', 'Italy': 'pizza', 'USA': 'hamburger', 'Spain': 'paella'}這里關(guān)于zip函數(shù)仍然有一個(gè)問題,如果兩個(gè)列表的長度不一致,會(huì)發(fā)生什么?其實(shí)很容易回答:多余的,沒有可配對(duì)的元素將被忽略。
>>> dishes = ["pizza", "sauerkraut", "paella", "hamburger"] >>> countries = ["Italy", "Germany", "Spain", "USA"," Switzerland"] >>> country_specialities = list(zip(countries, dishes)) >>> country_specialities_dict = dict(country_specialities) >>> print(country_specialities_dict) {'Germany': 'sauerkraut', 'Italy': 'pizza', 'USA': 'hamburger', 'Spain': 'paella'}參考文獻(xiàn):http://www.python-course.eu/python3_dictionaries.php
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
- 上一篇: 高效使用Google
- 下一篇: python列表的append和exte