13.python中的字典

来源:http://www.cnblogs.com/scolia/archive/2016/05/29/5538703.html
-Advertisement-
Play Games

字典其實和之前的元祖和列表功能相似,都是用來儲存一系列對象的。也就是一種可變容器,或者是我所比喻的革新派的菜單。 但也不是完全相同,我在之前曾經將字典稱為特殊的'序列',是字典擁有序列的部分特性,但是又不符合序列的定義。 首先我們來看下字典是如何創建的: 我們可以使用{} 或者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 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)
	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 偶然的機會接觸guava,對於我這種小白來說,google的東西當然是高大上的了,所以抱著學(裝)習(逼)的心態,在網上向前輩們學習了下。當然,我學guava主要也就幾個目的,首先當然是想著能否把guava應用在自己平日的代碼里,如果guava的引用能使代碼的書寫更加簡潔優雅,更著提升程式的性能,減 ...
  • 按照java面向對象的原則,每個基本類型都有對應的包裝類 byte Byte short Short int Integer long Long boolean Boolean float Float double Double char Character 最常用的作用是,基本類型與String字 ...
  • 最近又遇到了幾年前遇到的問題,標記一下。 對於跨位元組位域(bit field)而言,如果數據傳輸前後環境的位元組序不同(LE->BE,BE->LE),簡單地調用(ntohs/ntohl/htons/htonl)並不能正確讀取位域的值。 例如: 其中,tag,field2,pad是位元組內位域,field ...
  • 三、元組(tuple) 特點:Python的元組與列表類似,不同之處在於元組的元素不能修改,元組使用小括弧 四、列表(List) 五、字典(dict) ...
  • 二、運算符 三、基本數據類型 ...
  • 實現文件 ...
  • 設計模式(Design Patterns) ——可復用面向對象軟體的基礎 設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的, ...
  • 下麵的是學C++時要註意的。 1.把C++當成一門新的語言學習(和C沒啥關係!真的。); 2.看《Thinking In C++》,不要看《C++變成死相》; 3.看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因為他們 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...