第026講:字典:當索引不好用時2
目錄
0. Python的字典是否支援一鍵(Key)多值(Value)?
1. 在字典中,如果試圖為一個不存在的鍵(Key)賦值會怎樣?
2. 成員資格操作符(in和not in)可以檢查一個元素是否存在序列中,當然也可以用來檢查一個鍵(Key)是否存在字典中,那麼請問哪種的檢查效率更高些?為什麼?
3. Python對鍵(Key)和值(Value)有沒有型別限制?
5. 如果你需要將字典dict1 = {1: 'one', 2: 'two', 3: 'three'}拷貝到dict2,你應該怎麼做?
0. 嘗試編寫一個使用者登入程式(這次嘗試將功能封裝成函式),程式實現如圖:
1. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!
測試題
0. Python的字典是否支援一鍵(Key)多值(Value)?
答:不支援,對相同的鍵再次賦值會將上一次的值直接覆蓋。
>>> dict1 = {1:'one', 1:'yi'}
>>> dict1[1]
'yi'
1. 在字典中,如果試圖為一個不存在的鍵(Key)賦值會怎樣?
答:會自動建立對應的鍵(Key)並新增相應的值(Value)進去。(具體原理可以參考第3題的“擴充套件閱讀”部分)
2. 成員資格操作符(in和not in)可以檢查一個元素是否存在序列中,當然也可以用來檢查一個鍵(Key)是否存在字典中,那麼請問哪種的檢查效率更高些?為什麼?
答:在字典中檢查鍵(Key)是否存在比在序列中檢查指定元素是否存在更高效。因為字典的原理是使用雜湊演算法儲存,一步到位,不需要使用查詢演算法進行匹配,因此時間複雜度是O(1),效率非常高。(關於如何使用雜湊演算法儲存的具體原理可以參考第3題的“擴充套件閱讀”部分)
3. Python對鍵(Key)和值(Value)有沒有型別限制?
答:Python對鍵的要求相對要嚴格一些,要求它們必須是可雜湊(Hash)的物件,不能是可變型別(包括變數、列表、字典本身等)。
但是Python對值是沒有任何限制的,它們可以是任意的Python物件。
如果不清楚雜湊原理以及字典的存放原理的童鞋,推薦閱讀下小甲魚幫你整理的這篇文章:你知道Python的字典(Dict)是如何儲存的嗎?(
4. 請目測下邊程式碼執行後,字典dict1的內容是什麼?
>>> dict1.fromkeys((1, 2, 3), ('one', 'two', 'three'))
>>> dict1.fromkeys((1, 3), '數字')
答:執行完成後,字典dict1的內容是:{1: '數字', 3: '數字'}
這裡要注意的是,fromkeys方法是直接建立一個新的字典,不要試圖使用它來修改一個原有的字典,因為它會直接無情的用把整個字典給覆蓋掉。
5. 如果你需要將字典dict1 = {1: 'one', 2: 'two', 3: 'three'}拷貝到dict2,你應該怎麼做?
答:可以利用字典的copy()方法:dict2 = dict1.copy(),在其他語言轉移到Python小夥伴們剛開始可能會習慣性的直接用賦值的方法(dict2 = dict1),這樣子做在Python中只是將物件的引用拷貝過去而已。
看一下區別:
>>> a = {1:'one', 2:'two', 3:'three'}
>>> b = a.copy()
>>> c = a
>>> c[4] = 'four'
>>> c
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}
動動手
0. 嘗試編寫一個使用者登入程式(這次嘗試將功能封裝成函式),程式實現如圖:
user_data = {}
def new_user():
prompt = '請輸入使用者名稱:'
while True:
name = input(prompt)
if name in user_data:
prompt = '此使用者名稱已經被使用,請重新輸入:'
continue
else:
break
passwd = input('請輸入密碼:')
user_data[name] = passwd
print('註冊成功,趕緊試試登入吧^_^')
def old_user():
prompt = '請輸入使用者名稱:'
while True:
name = input(prompt)
if name not in user_data:
prompt = '您輸入的使用者名稱不存在,請重新輸入:'
continue
else:
break
passwd = input('請輸入密碼:')
pwd = user_data.get(name)
if passwd == pwd:
print('歡迎進入XXOO系統,請點右上角的X結束程式!')
else:
print('密碼錯誤!')
def showmenu():
prompt = '''
|--- 新建使用者:N/n ---|
|--- 登入賬號:E/e ---|
|--- 推出程式:Q/q ---|
|--- 請輸入指令程式碼:'''
while True:
chosen = False
while not chosen:
choice = input(prompt)
if choice not in 'NnEeQq':
print('您輸入的指令程式碼錯誤,請重新輸入:')
else:
chosen = True
if choice == 'q' or choice == 'Q':
break
if choice == 'n' or choice == 'N':
new_user()
if choice == 'e' or choice == 'E':
old_user()
showmenu()
1. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!
比序列更加使用的對映型別,Python唯一的一個對映型別就是字典,字典也有一個關鍵符號,就是大括號,跟序列一樣,也可以用 dict() 這個工廠函式來建立一個字典,跟序列不一樣的是,如果在序列中試圖為一個不存在的位置去賦值的時候,會報錯,會提示該位置並不存在,但如果在字典中,它會自動建立相應的鍵並新增對應的值。
dict() 是一個工廠函式,實際上是一個型別,呼叫它會生成一個該型別的例項,此前我們學習了str(),int(),list(),tuple(),這些都是工廠函式(型別),不過在學習類和物件之前,你可以把它們當做普通函式來理解。
1、下面介紹字典的內建方法
fromkeys(....)
用法:dict.fromkeys(S[ ,v]) -> New dict with keys from S and values equal to v(v default to None).
你可以用fromkeys(....)方法建立並返回新的字典,第一個引數S是字典的鍵值,第二個引數v是可選的鍵值對應的值,如果第二個引數不提供的話,就是None。
>>> dict1 = {}
>>> dict1.fromkeys((1, 2, 3))
{1: None, 2: None, 3: None}
>>> dict1
{}
dict1.fromkeys()只是建立新的字典,對原陣列無影響,和下面的程式碼是一樣的:
dict.fromkeys((1, 2, 3))
{1: None, 2: None, 3: None}
如果給鍵對應的值的話:
>>> dict.fromkeys((1, 2, 3), 'number')
{1: 'number', 2: 'number', 3: 'number'}
但是不要指望分別給鍵對應的值:
>>> dict.fromkeys((1, 2, 3), ('one', 'two', 'three'))
{1: ('one', 'two', 'three'), 2: ('one', 'two', 'three'), 3: ('one', 'two', 'three')}
2、下面介紹訪問字典的幾個方法
keys()、values()、items()
keys()返回字典鍵的引用,values()返回字典值的引用,items()返回字典項的引用
>>> dict1 = {1:'one', 2:'two', 3:'three', 4:'four', 5:'five'}
>>> dict1.keys()
dict_keys([1, 2, 3, 4, 5])
>>> dict1.values()
dict_values(['one', 'two', 'three', 'four', 'five'])
>>> dict1.items()
dict_items([(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four'), (5, 'five')])
>>> for eachkey in dict1.keys():
print(eachkey, end = ' ')
1 2 3 4 5
>>> for eachvalue in dict1.values():
print(eachvalue, end = ' ')
one two three four five
>>> for eachitem in dict1.items():
print(eachitem, end = ' ')
(1, 'one') (2, 'two') (3, 'three') (4, 'four') (5, 'five')
當我們試圖訪問字典中不存在的項時,就可能會報錯:
>>> dict1
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
>>> dict1[6]
Traceback (most recent call last):
File "<pyshell#56>", line 1, in <module>
dict1[6]
KeyError: 6
這樣的使用者體驗就會不好。
因此使用get()內建函式。
>>> dict1.get(5)
'five'
>>> dict1.get(6)
>>> print(dict1.get(6))
None
也可以在get中為不存在的項輸出相應的提示:
>>> dict1.get(6, '不存在')
'不存在'
>>> dict1.get(5, '不存在')
'five'
>>> dict1
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
如果不知道一個鍵是否在字典中(不能查詢值),可以使用成員資格操作符來進行判斷。in 和 not in
>>> 6 in dict1
False
>>> 5 in dict1
True
>>> 'five' in dict1
False
清空一個字典,使用clear()方法。
>>> dict1
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
>>> dict1.clear()
>>> dict1
{}
clear()會完全清除整個字典,即使該字典有多個名字對應:
>>> a = {1: 'one'}
>>> b = a
>>> b
{1: 'one'}
>>> a.clear()
>>> a
{}
>>> b
{}
copy()拷貝,區別於賦值:
>>> a = {1: 'one', 2: 'two', 3: 'three'}
>>> b = a.copy()
>>> c = a
>>> a
{1: 'one', 2: 'two', 3: 'three'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}
>>> c
{1: 'one', 2: 'two', 3: 'three'}
>>> id(a) id() 返回地址,可以發現c和a指向同一個字典
2200132871048
>>> id(b)
2200132857800
>>> id(c)
2200132871048
>>> c[4] = 'four'
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}
>>> c
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
pop()和popitem(),都是彈出字典中的元素。
>>> a = {1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a.pop(2)
'two'
>>> a
{1: 'one', 3: 'three', 4: 'four'}
>>> a = {1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a.popitem()
(1, 'one')
>>> a
{2: 'two', 3: 'three', 4: 'four'}
pop()是彈出對應鍵的項,返回鍵對應的值,popitem()是隨機從字典彈出項,返回鍵和值的元組。
setdefault()
用法與get()類似,只是如果找不到對應的鍵,會自動新增,值預設為None,也可以給值。
>>> a = {1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a.setdefault(2)
'two'
>>> a.setdefault(5)
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: None}
>>> a.setdefault(5, 'five')
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: None}
>>> a.setdefault(6, 'six')
'six'
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: None, 6: 'six'}
update(),用一個字典或對映關係去更新一個字典。
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: None, 6: 'six'}
>>> b = {2: 'double'}
>>> a.update(b)
>>> a
{1: 'one', 2: 'double', 3: 'three', 4: 'four', 5: None, 6: 'six'}