Python的字典
一、基本介紹
在Python中,如果沒有列表和字典是不可想象的。字典及其強有力的實現是使Python如此有效和出眾的重要原因。本文將展示字典及其使用方法。
字典和列表之間可以相互轉換,但字典和列表的不同之處在哪里?首先列表是有序的,而字典是無序的,但核心的不同在于字典是通過鍵(key)來訪問,而列表是通過位置訪問。更進一步講,字典是一種抽象數據類型的實現。字典的每一個鍵都與一個值相關聯。值可以是任意的Python數據類型。此外,字典不支持像位置索引、切片等序列操作方法。
二、字典實例
第一個例子是關于美國和加拿大的幾個大城市人口的,首先創建一個名為city的字典,字典中包含一些城市以及這些城市包含的人口數量:
>>> city = {"New York City":8175133, "Los Angeles": 3792621, "Washington":632323, "Chicago": 2695598, "Toronto":2615060, "Montreal":11854442, "Ottawa":883391, "Boston":62600}如果我們想得到某個城市的人口數量,我們可以直接用城市的名稱進行查詢:
>>> city["New York City"] 8175133 >>> city["Toronto"] 2615060 >>> city["Boston"] 62600如果我們用city中不存在的城市名稱作為key訪問,則會報錯。
>>> city["Detroit"] Traceback (most recent call last):File "<stdin>", line 1, in KeyError: 'Detroit'如果你回看下上面定義的字典city,你可能會覺得字典中的元素是有序的,例如,第一個是”New York City”, 第二個是 “Los Angeles” 等等,但事實上字典是無序的。我們再輸出查看下city,得到的順序可能與原始順序是不一樣的。
>>> city {'Toronto': 2615060, 'Ottawa': 883391, 'Los Angeles': 3792621, 'Chicago': 2695598, 'New York City': 8175133, 'Boston': 62600, 'Washington': 632323, 'Montreal': 11854442}因此,字典不能像列表一樣通過一個數字索引來訪問元素。
>>> 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}因此,通過往一個空字典中遞增式添加元素從而獲得所需字典的方式是可行的。前面還沒有提到如何創建一個空字典。如下是創建一個名字為city的空字典的方式:
>>> city = {} >>> city {}下一個例子是一個簡單的英德字典:
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"}現在,它可以從英語翻譯成法語了。盡管我們沒有一個英法字典,但是通過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),但是對鍵(key)是有約束的,只有不可變的類型才能作為鍵。如果用一個可變類型作為鍵,將會報錯。下面將一個列表作為鍵(key),因為列表是可變類型,所以報錯。
>>> 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'}我們還可以創建一個包含字典的字典:
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
三、字典操作
例子:
下面是一個拉丁字符與其對應摩爾斯碼的字典。
獲取字典中包含的拉丁字符數量可以調用len函數:
>>> len(morse) 38這個字典僅僅包含大寫字母,因此檢查小寫字母”a”是否在字典中將返回False:
>>> "a" in morse False >>> "A" in morse True >>> "a" not in morse Truelist可以像棧(stack)一樣使用pop()函數彈出一個元素。但是在字典中,因為是無序的并且沒有索引,所以pop()函數有著不一樣的含義。
如果D表示一個字典,那么D.pop(k)表示從D中移除鍵為k的元素,該操作的返回值是D[k]。
如果鍵k在D中不存在,那么將報錯。
如果我們試圖在上面的字典capitals中找到瑞士(Switzerland)的首都,由于不存在Switzerland,將報錯。為了避免這種錯誤,我們可以在pop()函數中使用第二個參數作為缺省值。
>>> 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()是字典的另一種方法,不需要任何輸入參數,將隨機移除字典中任意一個元素,返回值為該移除元素的鍵值對元組 (key,value)。如果是一個空字典,使用popitem()將報錯。
>>> 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') >>>如果我們訪問字典中不存在的鍵,將得到錯誤信息:
>>> locations = {"Toronto" : "Ontario", "Vancouver":"British Columbia"} >>> locations["Ottawa"] Traceback (most recent call last):File "<stdin>", line 1, in <module> KeyError: 'Ottawa'可以通過”in”操作符進行事先檢查,從而避免這個問題。
>>> if "Ottawa" in locations: print(locations["Ottawa"]) ... >>> if "Toronto" in locations: print(locations["Toronto"]) ... Ontario另一種訪問方式是通過get()方法,如果鍵不存在,get()方法不返回錯誤,而返回的是None。當然也可以設定一個鍵(key)不存在時缺省的返回值。
>>> 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'一個字典可以使用copy()函數進行復制:
>>> w = words.copy() >>> words["cat"]="chat" >>> print(w) {'house': 'Haus', 'cat': 'Katze'} >>> print(words) {'house': 'Haus', 'cat': 'chat'}這種拷貝是淺拷貝。如果字典中的值是一個復雜的數據類型,例如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中也發生了一樣的改變。
{'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'}}如果分配了一個新值給一個鍵,看看發生了什么:
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"])輸出結果:
{'trainer': 'Ella M. Charming', 'location': 'Berlin', 'title': 'Intermediate Python Training'}檢查下輸出,我們能看到改變trainings中course2的值,trainings2中course2卻沒有改變。如果你想了解這種現象產生的原因,可以回顧下前期文章《Python的淺拷貝和深拷貝》。
字典可以使用clear()函數清空,執行該方法后,字典本身沒有被刪除,而是被置為空字典。
>>> w.clear() >>> print(w) {}能不能將字典合并或歸并在一起呢,答案是肯定的。update()函數能夠歸并2個字典,如果存在相同的鍵,那么前一個字典該鍵下的值將被覆蓋:
>>> knowledge = {"Frank": {"Perl"}, "Monica":{"C","C++"}} >>> knowledge2 = {"Guido":{"Python"}, "Frank":{"Perl", "Python"}} >>> knowledge.update(knowledge2) >>> knowledge {'Frank': {'Python', 'Perl'}, 'Guido': {'Python'}, 'Monica': {'C', 'C++'}}對于字典的鍵(key)迭代,可以直接使用for循環和”in”操作符:
>>> d = {"a":123, "b":34, "c":304, "d":99} >>> for key in d: ... print(key) ... b c a d當然也可以使用keys()方法,能夠得到相同的效果:
>>> for key in d.keys(): ... print(key) ... b c a dvalues()方法能夠方便的對值(value)進行遍歷。
>>> for value in d.values(): ... print(value) ... 34 304 123 99上面的循環等價于如下的循環:
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四、列表和字典的相互轉換
list轉換成dict,或者dict轉換成list是使用python時經常會遇到的情況。我們可以通過dict的item()、keys()和values()方法來創建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'])下面再看看列表如何轉換成字典。我們有兩個列表,一個包含各種美食,一個是與這些美食相對應的國家。
>>> dishes = ["pizza", "sauerkraut", "paella", "hamburger"] >>> countries = ["Italy", "Germany", "Spain", "USA"]現在我們創建一個字典,將國家作為key,將該國家對應的美食作為value。首先構建一個新列表,這里我們使用了zip函數。
>>> country_specialities = list(zip(countries, dishes)) >>> print(country_specialities) [('Italy', 'pizza'), ('Germany', 'sauerkraut'), ('Spain', 'paella'), ('USA', 'hamburger')]然后通過dict()方法將列表轉換成字典。
>>> country_specialities_dict = dict(country_specialities) >>> print(country_specialities_dict) {'Germany': 'sauerkraut', 'Italy': 'pizza', 'USA': 'hamburger', 'Spain': 'paella'}這里關于zip函數仍然有一個問題,如果兩個列表的長度不一致,會發生什么?其實很容易回答:多余的,沒有可配對的元素將被忽略。
>>> 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'}參考文獻:http://www.python-course.eu/python3_dictionaries.php
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: 高效使用Google
- 下一篇: python列表的append和exte