程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Python >> python中的字典

python中的字典

編輯:Python

  字典其實和之前的元祖和列表功能相似,都是用來儲存一系列對象的。也就是一種可變容器,或者是我所比喻的革新派的菜單。

  但也不是完全相同,我在之前曾經將字典稱為特殊的'序列',是字典擁有序列的部分特性,但是又不符合序列的定義。

  首先我們來看下字典是如何創建的:

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 T
dict

   按照其功能可分為:

  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中的對象這裡並沒有做處理,就相當於多出來的就扔到垃圾桶裡去了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved