字典其實和以前的元祖和列表功能類似,都是用來儲存一系列對象的。也就是一種可變容器,或者是我所比喻的革新派的菜單。html
但也不是徹底相同,我在以前曾經將字典稱爲特殊的'序列',是字典擁有序列的部分特性,可是又不符合序列的定義。python
首先咱們來看下字典是如何建立的:app
a = {'a':1,'b':2,'c':2} b = {} c = dict(a=1) print a print b print c
咱們可使用{} 或者dict() 來建立一個字典對象。ide
但字典裏面寫的是什麼?下面我來分析一下。函數
首先,字典是以鍵值對的形式來儲存對象的,即 key:value ,鍵和值之間用冒號分隔,而每一個鍵值對之間用逗號分隔。學習
這個是時候能夠聯想一下序列的形式,在序列中,對象之間也是用逗號分隔的,但不一樣的是,序列是使用索引做爲key,且索引是提取定義好的,按照必定順序的。可是字典中,key是自定義的,至關於咱們爲對象起一個變量名,只不過變量名在字典的key中是以字符串的形式存在的,就像 c 中的建立方式,變量名爲 a ,最終獲得的鍵爲 'a'。優化
那是否是字典的鍵就只能是字符串類型呢?並非,咱們也能夠像序列同樣用數字做爲鍵。ui
a = {666:'scolia',} print a
固然,爲了提升代碼可讀性,我在只有單個對象的時候仍是用了逗號。this
元祖和列表也能夠做爲鍵嗎?spa
答案是:NO!
雖然說幾乎全部類型的python對象都能做爲鍵(只要該對象是可哈希的),可是通常仍是以數字或者字符串最爲經常使用。
看到這裏,咱們可能會想字典無非就是高級一點的列表而已,爲何又不是序列呢?
由於字典是無序的。
咱們看變量 a 中的字典:
a = {'a':1,'b':2,'c':2}
咱們在建立的時候明明是按必定順序排列的,爲何輸出的時候順序卻亂了?
這正是字典無序性的體現。
首先序列之因此被稱爲序列:正如其名,有序的、隊列式的。咱們在序列中逐一放入元素的時候,會自動的按照從左到右進行編號,也就是索引,而每個索引對應一個對象。而字典卻失去了索引的約束,用了自定義的鍵來取代,當咱們在獲取對象時也是用鍵名來獲取,只要知道了鍵名,那麼對象在字典中的哪一個位置也無所謂了,因此字典是無序的,也就不能稱爲序列。
但咱們依然能夠將其想象爲是一種高級的列表,只不過這個列表的索引是自定義的,無序的。
另外,當字典中的出現了同名的鍵會怎麼辦?
a = {'scolia': 1,'scolia':2,'scolia':3} print a
就像變量命名同樣,前面的都被衝突掉了。
這時又有同窗問:不是說字典是無序的嗎?我怎麼知道誰在前誰在後?
我曾經把索引比做是特殊的變量名,只不過普通的變量名不能只是數字,而索引則是經過數字去內存取值。同理,字典裏的鍵也能夠看做是變量名,在字典裏的元素打包成一個字典以前,先進行了變量的賦值操做,而對同一個變量進行屢次賦值至關於切換其在內存的引用,只有最後一個賦值有效,這裏也是同樣的。在鍵值對建立的時候,按照咱們寫時候的順序先進行賦值操做,而後保存在字典中,保存以後纔是無序的。
那麼值相同的時候是否也是同一個對象呢?
a = {'a':300,'b':300} print id(a['a']),id(a['b'])
看來是的,和序列中的同樣,也是節省內存的優化。
接下來咱們就能夠開始學習字典的內置方法了,首先按老規矩先使用 help(dict) 查看其幫助文檔。
Help on class dict in module __builtin__: class dict(object) | dict() -> new empty dictionary | dict(mapping) -> new dictionary initialized from a mapping object's | (key, value) pairs | dict(iterable) -> new dictionary initialized as if via: | d = {} | for k, v in iterable: | d[k] = v | dict(**kwargs) -> new dictionary initialized with the name=value pairs | in the keyword argument list. For example: dict(one=1, two=2) | | Methods defined here: | | __cmp__(...) | x.__cmp__(y) <==> cmp(x,y) | | __contains__(...) | D.__contains__(k) -> True if D has a key k, else False | | __delitem__(...) | x.__delitem__(y) <==> del x[y] | | __eq__(...) | x.__eq__(y) <==> x==y | | __ge__(...) | x.__ge__(y) <==> x>=y | | __getattribute__(...) | x.__getattribute__('name') <==> x.name | | __getitem__(...) | x.__getitem__(y) <==> x[y] | | __gt__(...) | x.__gt__(y) <==> x>y | | __init__(...) | x.__init__(...) initializes x; see help(type(x)) for signature | | __iter__(...) | x.__iter__() <==> iter(x) | | __le__(...) | x.__le__(y) <==> x<=y | | __len__(...) | x.__len__() <==> len(x) | | __lt__(...) | x.__lt__(y) <==> x<y | | __ne__(...) | x.__ne__(y) <==> x!=y | | __repr__(...) | x.__repr__() <==> repr(x) | | __setitem__(...) | x.__setitem__(i, y) <==> x[i]=y | | __sizeof__(...) | D.__sizeof__() -> size of D in memory, in bytes | | clear(...) | D.clear() -> None. Remove all items from D. | | copy(...) | D.copy() -> a shallow copy of D | | fromkeys(...) | dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. | v defaults to None. | | get(...) | D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None. | | has_key(...) | D.has_key(k) -> True if D has a key k, else False | | items(...) | D.items() -> list of D's (key, value) pairs, as 2-tuples | | iteritems(...) | D.iteritems() -> an iterator over the (key, value) items of D | | iterkeys(...) | D.iterkeys() -> an iterator over the keys of D | | itervalues(...) | D.itervalues() -> an iterator over the values of D | | keys(...) | D.keys() -> list of D's keys | | pop(...) | D.pop(k[,d]) -> v, remove specified key and return the corresponding value. | If key is not found, d is returned if given, otherwise KeyError is raised | | popitem(...) | D.popitem() -> (k, v), remove and return some (key, value) pair as a | 2-tuple; but raise KeyError if D is empty. | | setdefault(...) | D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D | | update(...) | D.update([E, ]**F) -> None. Update D from dict/iterable E and F. | If E present and has a .keys() method, does: for k in E: D[k] = E[k] | If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v | In either case, this is followed by: for k in F: D[k] = F[k] | | values(...) | D.values() -> list of D's values | | viewitems(...) | D.viewitems() -> a set-like object providing a view on D's items | | viewkeys(...) | D.viewkeys() -> a set-like object providing a view on D's keys | | viewvalues(...) | D.viewvalues() -> an object providing a view on D's values | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __hash__ = None | | __new__ = <built-in method __new__ of type object> | T.__new__(S, ...) -> a new object with type S, a subtype of T
按照其功能可分爲:
1.大於、小於、等於等比較運算符
2.成員判斷
3.內置函數相關的(參考這裏)
4.增刪改查相關操做
1.比較運算符
由於字典不是序列了,因此就不能像序列同樣按照索引逐個打擂臺了。
不過大小的比較規則仍是同樣的,只是上場的順序未知而已。
那到底比較的時候順序是怎麼樣的,看下面的例子。
a = {'a':1,'b':2,'c':3} for x in a: print x
咱們使用for循環來看看比較時的順序,能夠看出,順序是無可預估的,雖然這裏只有三個鍵值對,貌似有必定的規律,可是一旦裏面的對象多起來,就得不出規律了,並且不可能每次比較的時候都要本身看一下里面是怎麼比的,那樣實在太累,因此咱們得出一個結論:少用字典間的比較,要比較用序列去。
另外這裏補充一點:當咱們使用for循環時,咱們獲得的是鍵名,若是咱們要取到值怎麼辦?能夠像下面這樣寫:
a = {'a':1,'b':2,'c':3} for x in a: print a[x]
固然還有其餘寫法,看完內置方法後本身總結吧。
2.成員判斷
1. in
在序列中判斷裏面有沒有某個元素時使用的是 in ,但細心的同窗會發現,在幫助文檔中並無出現 in ,是否是in不能用了呢?
看下面這個例子:
a = {'a':1,'b':2, 3:30} b = 2 print b in a print 2 in a print 'b' in a print 3 in a
還可使用,可是這裏 in 只能判斷字典裏是否有哪一個鍵,而不是鍵對應的值。
2. D.has_key(k) -> True if D has a key k, else False
和 in 同樣,判斷裏面是否有某個鍵,返回布爾值。
a = {'a':1,'b':2, 3:30} print a.has_key('b') print a.has_key(3)
3. D.__contains__(k) -> True if D has a key k, else False
判斷是否有某個鍵,和上面的同樣,就很少說明了。
4.判斷字典裏面是否有某個對象。
字典中並無內置的方法能直接判斷,可是咱們能夠本身寫一個。
a = {'a':1,'b':2, 3:30} b = 30 c = a.values() #返回一個由字典的值組成的列表 print c #一樣咱們沒法預估字典裏的順序 print b in c
咱們轉了一個彎,這就要考驗思惟的靈活性了。
3.增
1. x.__setitem__(i, y) <==> x[i]=y
這個和列表中的不一樣,列表的這個寫法是修改元素,若是給的索引不存在是會報錯的。但在字典中,這個方法除了能夠用來修改元素以外,若是給定的鍵不存在,則會在字典中建立這個鍵值對。
a = {'a':1,'b':2, 3:30} a['scolia'] = 'good' print a
2. dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v. v defaults to None.
這個方法用於建立新的字典對象,我這裏將其歸類到這裏。
其中,S 爲一個鍵的序列,v爲值,將爲S所指定的全部鍵設置同一個值,默認爲None。
a = dict.fromkeys(('scolia'),123) b = dict.fromkeys(('scolia',)) print a print b
注意S的寫法,這就是爲何在元祖只有一個元素的時候必定要加一個逗號,不然解釋器會將其看成傳參,將字符串傳進去,而字符串也是一個序列,因此沒一個字符都被當作一個鍵,就形成了a的輸出了。將S寫成一個列表就不會有這樣的錯誤,但元祖消耗的資源少,具體選擇看我的。
a = dict.fromkeys(['scolia'],123) print a
a = {'scolia': 1,'good':1,1:0} print a.fromkeys(('k'),123) print a
這裏很特殊,建立的對象並無添加到原字典中,而是所爲一個返回值。
3. D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
這是一個集查詢、修改、增長鍵值對的方法。
a = dict.fromkeys(['scolia'],123) print a.setdefault('s',123) print a
這裏解釋這個方法的細節:首先k是必須的參數,若是隻給k一個參數,則d默認爲None,也能夠指定d的值。
a = dict.fromkeys(['scolia'],123) print a.setdefault('scolia') print a.setdefault('s') print a
其執行順序爲:
1.先用給定的k看看裏面有沒有對應的鍵,有就返回這個鍵的值。
2.若是沒有k這個鍵,則建立這個鍵,而後用d做爲其值,若是d沒給就默認爲None(空對象)。
4.刪
1. del x[y]
用del關鍵字刪除對象,在列表中講過,只不過y從索引變成了鍵名。這裏再也不重複。
2. D.clear() -> None. Remove all items from D.
刪除整個字典裏的元素,返回值爲None。
a ={'scolia':123} print a.clear() print a
不須要傳參,但要注意就算清空了字典裏的因此元素,最後獲得的仍是一個空字典,而不是空對象None。
3. D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
刪除指定的鍵值對,並返回相應的值。若是沒找到鍵返回d,若連d都沒給,則觸發KeyError錯誤。
a ={'scolia':123,123:321} print a.pop(123) print a.pop(666,'沒找到') print a.pop(999)
4. D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty.
刪除字典中的第一個元素,並將其按一個元祖返回,若是字典爲空則觸發KeyError錯誤
a ={'scolia':123,123:321,555:777} print a print a.popitem() print a
但仍是那句話,字典中元素的順序是未知的,誰知道第一個是什麼,因此多配合迭代循環使用,逐個刪除掉。
5.查
1. D.keys() -> list of D's keys
返回一個由鍵組成的列表
a ={'scolia':123,123:321,555:777} print a.keys()
2. D.values() -> list of D's values
返回一個由值組成的列表
a ={'scolia':123,123:321,555:777} print a.values()
3. D.items() -> list of D's (key, value) pairs, as 2-tuples
返回一個由鍵值組成的元祖的列表。
a ={'scolia':123,123:321,555:777} print a.items()
4. D.iterkeys() -> an iterator over the keys of D
返回一個包含全部鍵的迭代對象
a ={'scolia':123,123:321,555:777} b = a.iterkeys() for x in b: print x
5. D.itervalues() -> an iterator over the values of D
返回一個包含全部值的迭代對象,原理同上,再也不詳細說明。
6. D.iteritems() -> an iterator over the (key, value) items of D
返回一個包含鍵值對元祖的迭代對象,同理。另外注意下元祖的迭代循環技巧。
7. D.viewkeys() -> a set-like object providing a view on D's keys
返回一個鍵的相似集合的對象。集合的做用是去除重複,但字典對於鍵的重複已經有相應處理,感受意義不大。
a = {'scolia': 1,'scolia':2,1:123} print a.viewkeys() print type(a.viewkeys())
8. D.viewvalues() -> an object providing a view on D's values
返回一個值的視圖對象,注意不是集合對象,沒有去重做用。
a = {'scolia': 1,'good':1,1:123} print a.viewvalues() print type(a.viewvalues())
9. D.viewitems() -> a set-like object providing a view on D's items
返回一個由鍵和值組成的元祖的類集合對象。
a = {'scolia': 1,'good':1,1:123} print a.viewitems() print type(a.viewitems())
一樣感受意義不大,緣由同上。
6.改
1. x[i]=y
和列表中的相似,只是 i 不是索引而是鍵名,當鍵名不存在時,就至關於新增鍵值對了。這裏不重複說明了。
2. D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
上面講過了,再也不重複
3. D.update([E, ]**F) -> None.
從字典或可迭代對象E和F中,更新元素到字典D中。這裏其實也能夠歸類到增長對象那裏去,但字典的增操做和改操做其實不少方法是能夠相通的,這裏就放到這裏了,讓這裏看起來不會太單薄。
這裏的**F的寫法實際上是解決冗餘參數的寫法,詳細咱們會在函數中講。
當E .key() 有方法時。
for k in E: D[k] = E[k]
即當E也是字典時,咱們能夠將一個字典添加到另外一個字典中:
a = {'scolia': 1,'good':1} b = {'scolia':2, 666:999} a.update(b) print a
print b
a中的同名鍵會被b的覆蓋掉,且不會影響b自己。
當E沒有.key()方法時。
for (k, v) in E: D[k] = v
即E爲二元元祖序列,以二元元祖中的第一個元素爲鍵,第二個元素爲值,添加到字典中。
a = {'scolia': 1,'good':1,1:0} b = [('a',123),('b',321),(1,1)] a.update(b) print a
所謂二元元祖序列,即裏面放多個元祖,每一個元祖只有兩個元素,而其外層爲序列,元祖、列表都行。
注意:有些同窗在學完函數後可能會糾結,**F其實也算是一個字典,那我傳進去的字典到底是傳給了誰?
首先**F是處理冗餘參數的,要想有做用,首先參數要超過須要的,而當咱們傳一個字典或其餘對象的時候,是傳給了E,當傳多個對象的時候,多出來的就到了**F中了,而**F中的對象這裏並無作處理,就至關於多出來的就扔到垃圾桶裏去了。