字典其實和之前的元祖和列表功能相似,都是用來儲存一系列對象的。也就是一種可變容器,或者是我所比喻的革新派的菜單。 但也不是完全相同,我在之前曾經將字典稱為特殊的'序列',是字典擁有序列的部分特性,但是又不符合序列的定義。 首先我們來看下字典是如何創建的: 我們可以使用{} 或者dict() 來創建一 ...
字典其實和之前的元祖和列表功能相似,都是用來儲存一系列對象的。也就是一種可變容器,或者是我所比喻的革新派的菜單。
但也不是完全相同,我在之前曾經將字典稱為特殊的'序列',是字典擁有序列的部分特性,但是又不符合序列的定義。
首先我們來看下字典是如何創建的:
a = {'a':1,'b':2,'c':2} b = {} c = dict(a=1) print a print b print c
我們可以使用{} 或者dict() 來創建一個字典對象。
但字典裡面寫的是什麼?下麵我來分析一下。
首先,字典是以鍵值對的形式來儲存對象的,即 key:value ,鍵和值之間用冒號分隔,而每個鍵值對之間用逗號分隔。
這個是時候可以聯想一下序列的形式,在序列中,對象之間也是用逗號分隔的,但不同的是,序列是使用索引作為key,且索引是提取定義好的,按照一定順序的。但是字典中,key是自定義的,相當於我們為對象起一個變數名,只不過變數名在字典的key中是以字元串的形式存在的,就像 c 中的創建方式,變數名為 a ,最終得到的鍵為 'a'。
那是不是字典的鍵就只能是字元串類型呢?並不是,我們也可以像序列一樣用數字作為鍵。
a = {666:'scolia',} print a
當然,為了提高代碼可讀性,我在只有單個對象的時候還是用了逗號。
元祖和列表也可以作為鍵嗎?
答案是:NO!
看來鍵要求精確單一的對象,使用容器作為鍵肯定是不行的。當然值可以是任何對象,和元祖、列表一樣。
看到這裡,我們可能回想字典無非就是高級一點的列表而已,為什麼又不是序列呢?
因為字典是無序的。
我們看變數 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 Tdict
按照其功能可分為:
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)