什麼是數據類型?html
咱們人類能夠很容易的分清數字與字符的區別,可是計算機並不能呀,計算機雖然很強大,但從某種角度上看又很傻,除非你明確的告訴它,1是數字,「漢」是文字,不然它是分不清1和‘漢’的區別的,所以,在每一個編程語言裏都會有一個叫數據類型的東東,其實就是對經常使用的各類數據類型進行了明確的劃分,你想讓計算機進行數值運算,你就傳數字給它,你想讓他處理文字,就傳字符串類型給他。Python中經常使用的數據類型有多種,以下:java
整數(int) ,字符串(str),布爾值(bool),列表(list),元組(tuple),字典(dict),集合(set).python
nt,就是我們常見的數據類型,主要是用於葛總運算,加減乘數等這裏就不給你舉例說明了。linux
首先要給你們講下是十進制與二進制之間的轉換。算法
2.1.1 十進制二進制轉換編程
十進制整數轉換爲二進制整數採用"除2取餘,逆序排列"法。具體作法是:用2整除十進制整數,能夠獲得一個商和餘數;再用2去除商,又會獲得一個商和餘數,如此進行,直到商爲小於1時爲止,而後把先獲得的餘數做爲二進制數的低位有效位,後獲得的餘數做爲二進制數的高位有效位,依次排列起來。api
十進制小數轉換成二進制小數採用"乘2取整,順序排列"法。具體作法是:用2乘十進制小數,能夠獲得積,將積的整數部分取出,再用2乘餘下的小數部分,又獲得一個積,再將積的整數部分取出,如此進行,直到積中的小數部分爲零,此時0或1爲二進制的最後一位。或者達到所要求的精度爲止。數組
二進制轉化成十進制: 安全
要從右到左用二進制的每一個數去乘以2的相應次方,小數點後則是從左往右數據結構
例如:二進制數1101.01轉化成十進制
1101.01(2)=1*20+0*21+1*22+1*23 +0*2-1+1*2-2=1+0+4+8+0+0.25=13.25(10)
因此總結起來通用公式爲:
abcd.efg(2)=d*20+c*21+b*22+a*23+e*2-1+f*2-2+g*2-3(10)
或者是:
把二進制數首先寫成加權係數展開式,而後按十進制加法規則求和。這種作法稱爲"按權相加"法。
此時,1101=8+4+0+1=13
再好比:二進制數100011轉成十進制數能夠看做這樣:
數字中共有三個1 即第一位一個,第五位一個,第六位一個,而後對應十進制數即2的0次方+2的1次方+2的5次方, 即
100011=32+0+0+0+2+1=35
2.2.2 int操做方法
由於數字主要是用於計算,因此針對於數字可使用的方法除了那些運算以外,沒有什麼常常會用的方法,python給我們提供了一種方法:bit_length()就是幫助你快速的計算整數在內存中佔用的二進制碼的長度.
num = 10 print(num.bit_length()) # 當十進制用二進制表示時,最少使用的位數
# 運行結果: 4
布爾值就兩種:True,False。就是反應條件的正確與否。
真 1 True。
假 0 False。
這裏補充一下int str bool 三者數據類型之間的轉換。
# int ---> bool
i = 100
print(bool(i)) # True # 非零即True
i1 = 0
print(bool(i1)) # False 零即False
# bool ---> int
t = True
print(int(t)) # 1 True --> 1
t = False
print(int(t)) # 0 False --> 0
# int ---> str
i1 = 100
print(str(i1)) # '100'
# str ---> int # 所有由數字組成的字符串才能夠轉化成數字
s1 = '90'
print(int(s1)) # 90
# str ---> bool
s1 = '太白'
s2 = ''
print(bool(s1)) # True 非空即True
print(bool(s2)) # False
# bool ---> str
t1 = True
print(str(True)) # 'True'
Python中凡是用引號引發來的數據能夠稱爲字符串類型,組成字符串的每一個元素稱之爲字符,將這些字符一個一個鏈接起來,而後在用引號起來就是字符串。
s1 = '太白nb' # 對於s1這個字符串來講,它由四個字符組成:太, 白, n, b。
2.3.一、字符串的索引與切片。
組成字符串的字符從左至右,依次排列,他們都是有順序的,就比如是部隊的隊列,從左至右依次報號(從零開始) :0,1,2,3....
索引即下標,就是字符串組成的元素從第一個開始,初始索引爲0以此類推。
a = 'ABCDEFGHIJK' print(a[0]) print(a[3]) print(a[5]) print(a[7])
切片就是經過索引(索引:索引:步長)截取字符串的一段,造成新的字符串(原則就是顧頭不顧腚)。
a = 'ABCDEFGHIJK' print(a[0:3]) # print(a[:3]) 從開頭開始取0能夠默認不寫 print(a[2:5]) print(a[:]) #默認到最後 print(a[:-1]) # -1 是列表中最後一個元素的索引,可是要知足顧頭不顧腚的原則,因此取不到K元素 print(a[:5:2]) #加步長
print(a[-1:-5:-2]) #反向加步長
2.3.二、字符串經常使用方法。
字符串除了能夠用切片(步長)以外,還有一些其餘的操做方法。
#數字符串中的元素出現的個數。
# ret3 = a1.count("a",0,4) # 可切片
# print(ret3)
a4 = "dkfjdkfasf54"
#startswith 判斷是否以...開頭
#endswith 判斷是否以...結尾
# ret4 = a4.endswith('jdk',3,6) # 顧頭不顧腚
# print(ret4) # 返回的是布爾值
# ret5 = a4.startswith("kfj",1,4)
# print(ret5)
#split 以什麼分割,最終造成一個列表此列表不含有這個分割的元素。
# ret9 = 'title,Tilte,atre,'.split('t')
# print(ret9)
# ret91 = 'title,Tilte,atre,'.rsplit('t',1)
# print(ret91)
#format的三種玩法 格式化輸出
res='{} {} {}'.format('egon',18,'male')
res='{1} {0} {1}'.format('egon',18,'male')
res='{name} {age} {sex}'.format(sex='male',name='egon',age=18)
#strip
name='*barry**'
print(name.strip('*'))
print(name.lstrip('*'))
print(name.rstrip('*'))
#replace
name='alex say :i have one tesla,my name is alex'
print(name.replace('alex','SB',1))
#####is系列
name='taibai123'
print(name.isalnum()) #字符串由字母或數字組成
print(name.isalpha()) #字符串只由字母組成
print(name.isdecimal()) #字符串只由十進制組成
#############下面這些方法在數據類型補充時會講到,如今不講####################
#尋找字符串中的元素是否存在
# ret6 = a4.find("fjdk",1,6)
# print(ret6) # 返回的找到的元素的索引,若是找不到返回-1
# ret61 = a4.index("fjdk",4,6)
# print(ret61) # 返回的找到的元素的索引,找不到報錯。
#captalize,swapcase,title
print(name.capitalize()) #首字母大寫
print(name.swapcase()) #大小寫翻轉
msg='taibai say hi'
print(msg.title()) #每一個單詞的首字母大寫
# 內同居中,總長度,空白處填充
ret2 = a1.center(20,"*")
print(ret2)
Why: 咱們如今已經學過的數據類型有:數字,布爾值,字符串,你們都知道數字主要用於計算,bool值主要是條件判斷,只有字符串能夠用於數據的存儲,這些數據類型夠用麼?對於一門語言來講,確定是不夠用的。就說字符串:
1,字符串只能存儲少許的數據,對於大量的數據用字符串操做不方便也不易存儲。
2,字符串存儲的數據類型太單一,只能是字符串類型。
例如:‘1 True alex’ 像這樣的字符串,我若是經過切片或者其餘方法將1 True alex 取出來,他也只能是字符串,可是我想要獲得數字的1,布爾值的True,必須還要轉化,是否是很麻煩。
因此python給我們也提供了一類數據類型,他能承載多種數據類型,這類數據類型被稱做容器類數據類型能夠存儲大量的數據。列表就屬於容器類的數據類型。
What:這個數據類型就是list列表。
列表是python的基礎數據類型之一 ,其餘編程語言也有相似的數據類型.好比JS中的數 組, java中的數組等等. 它是以[ ]括起來, 每一個元素用' , '隔開並且能夠存放各類數據類型: 列表是python中的基礎數據類型之一,其餘語言中也有相似於列表的數據類
型,好比js中叫數組,他是以[]括起來,每一個元素以逗號隔開,並且他裏面能夠存放各類數據類型好比:
li = [‘alex’,123,Ture,(1,2,3,’wusir’),[1,2,3,’小明’,],{‘name’:’alex’}]
列表相比於字符串,不只能夠儲存不一樣的數據類型,並且能夠儲存大量數據,32位python的限制是 536870912 個元素,64位python的限制是 1152921504606846975 個元素。並且列表是有序的,有索引值,可切片,方便取值。
How:那麼這個列表如何使用呢?我們從這幾方面去深刻研究這個列表。
2.4.1 列表的建立
# 建立一個列表有三種方式: # 方式一:(經常使用) l1 = [1, 2, '太白'] # 方式二:(不經常使用) l1 = list() # 空列表 # l1 = list(iterable) # 可迭代對象 l1 = list('123') print(l1) # ['1', '2', '3'] # 方式三:列表推導式(後面的課程會講到) l1 = [i for i in range(1,5)] print(l1) # [1, 2, 3, 4]
2.4.2 列表的索引切片
l1 = ['a', 'b', '太白', 3, 666]
print(l1[0]) # 'a'
print(l1[-1]) # 666
print(l1[1:3]) # ['b', '太白']
print(l1[:-1]) # ['a', 'b', '太白', 3]
print(l1[::2]) # ['a', '太白', 666]
print(l1[::-1]) # [666, 3, '太白', 'b', 'a']
li = [1, 3, 2, "a", 4, "b", 5,"c"] 經過對li列表的切片造成新的列表l1,l1 = [1,3,2] 經過對li列表的切片造成新的列表l2,l2 = ["a",4,"b"] 經過對li列表的切片造成新的列表l4,l4 = [3,"a","b"] 經過對li列表的切片造成新的列表l6,l6 = ["b","a",3]
2.4.3. 增
# append 追加,給列表的最後面追加一個元素
l = [1, 2, 'a']
l.append(666)
print(l) # [1, 2, 'a', 666]
# insert 插入在列表的任意位置插入元素
l = [1, 2, 'a']
l.insert(1,'太白')
print(l) # [1, '太白', 2, 'a']
# extend 迭代着追加,在列表的最後面迭代着追加一組數據
l = [1, 2, 'a']
l.extend('太白a')
print(l)
列表的增
2.4.4. 刪
# pop 經過索引刪除列表中對應的元素,該方法有返回值,返回值爲刪除的元素
l = ['太白', 'alex', 'WuSir', '女神']
ret = l.pop(1)
print(ret,l) # alex ['太白', 'WuSir', '女神']
# remove 經過元素刪除列表中該元素
l = ['太白', 'alex', 'WuSir', '女神']
l.remove('alex')
print(l) # ['太白', 'WuSir', '女神']
# clear 清空列表
l = ['太白', 'alex', 'WuSir', '女神']
l.clear()
print(l) # []
# del
#按照索引刪除該元素
l = ['太白', 'alex', 'WuSir', '女神']
del l[2]
print(l) # ['太白', 'alex', '女神']
# 切片刪除該元素
l = ['太白', 'alex', 'WuSir', '女神']
del l[1:]
print(l) # ['太白']
# 切片(步長)刪除該元素
l = ['太白', 'alex', 'WuSir', '女神']
del l[::2]
print(l) # ['alex', '女神']
列表的刪
2.4.5. 改
# 按照索引改值
l = ['太白', 'alex', 'WuSir', '女神']
l[0] = '男神'
print(l) # ['男神', 'alex', 'WuSir', '女神']
# 按照切片改值(迭代着增長)
l = ['太白', 'alex', 'WuSir', '女神']
l[1:3] = 'abcdefg'
print(l) # ['太白', 'a', 'b', 'c', 'd', 'e', 'f', 'g', '女神']
# 按照切片(步長)改值(必須一一對應)
l = ['太白', 'alex', 'WuSir', '女神']
l[::2] = '對應'
print(l) # ['對', 'alex', '應', '女神']
列表的改
2.4.6. 查
切片去查,或者循環去查。
2.4.5 其餘操做這些方法會在數據類型的補充時再給你們講~
2.4.五、其餘操做
count(數)(方法統計某個元素在列表中出現的次數)。
1 a = ["q","w","q","r","t","y"] 2 print(a.count("q"))
index(方法用於從列表中找出某個值第一個匹配項的索引位置)
1 a = ["q","w","r","t","y"] 2 print(a.index("r"))
sort (方法用於在原位置對列表進行排序)。
reverse (方法將列表中的元素反向存放)。
1 a = [2,1,3,4,5] 2 a.sort()# 他沒有返回值,因此只能打印a 3 print(a) 4 a.reverse()#他也沒有返回值,因此只能打印a 5 print(a)
列表也能夠相加與整數相乘
l1 = [1, 2, 3] l2 = [4, 5, 6] # print(l1+l2) # [1, 2, 3, 4, 5, 6] print(l1*3) # [1, 2, 3, 1, 2, 3, 1, 2, 3]
l1 = [1, 2, 3] l2 = [4, 5, 6] # print(l1+l2) # [1, 2, 3, 4, 5, 6] print(l1*3) # [1, 2, 3, 1, 2, 3, 1, 2, 3]
li = ["alex", "WuSir", "ritian", "barry", "wenzhou"]
計算列表的長度並輸出
列表中追加元素"seven",並輸出添加後的列表
請在列表的第1個位置插入元素"Tony",並輸出添加後的列表
請修改列表第2個位置的元素爲"Kelly",並輸出修改後的列表
請將列表l2=[1,"a",3,4,"heart"]的每個元素添加到列表li中,一行代碼實現,不容許循環添加。
請將字符串s = "qwert"的每個元素添加到列表li中,一行代碼實現,不容許循環添加。
請刪除列表中的元素"ritian",並輸出添加後的列表
請刪除列表中的第2個元素,並輸出刪除的元素和刪除元素後的列表
請刪除列表中的第2至4個元素,並輸出刪除元素後的列表
相應練習題
li = ["alex", "WuSir", "ritian", "barry", "wenzhou"] 計算列表的長度並輸出 列表中追加元素"seven",並輸出添加後的列表 請在列表的第1個位置插入元素"Tony",並輸出添加後的列表 請修改列表第2個位置的元素爲"Kelly",並輸出修改後的列表 請將列表l2=[1,"a",3,4,"heart"]的每個元素添加到列表li中,一行代碼實現,不容許循環添加。 請將字符串s = "qwert"的每個元素添加到列表li中,一行代碼實現,不容許循環添加。 請刪除列表中的元素"ritian",並輸出添加後的列表 請刪除列表中的第2個元素,並輸出刪除的元素和刪除元素後的列表 請刪除列表中的第2至4個元素,並輸出刪除元素後的列表
2.4.6 列表的嵌套
l1 = [1, 2, 'taibai', [1, 'WuSir', 3,]] 1, 將l1中的'taibai'變成大寫並放回原處。 2,給小列表[1,'alex',3,]追加一個元素,'老男孩教育'。 3,將列表中的'alex'經過字符串拼接的方式在列表中變成'alexsb'
lis = [2, 3, "k", ["qwe", 20, ["k1", ["tt", 3, "1"]], 89], "ab", "adv"] 將列表lis中的"tt"變成大寫(用兩種方式)。 將列表中的數字3變成字符串"100"(用兩種方式)。 將列表中的字符串"1"變成數字101(用兩種方式)。
Where:(這個知識點用在什麼地方):
你須要存儲大量的數據,且須要這些數據有序的時候。
制定一些特殊的數據羣體:按順序,按規則,自定製設計數據。
Why:對於容器型數據類型list,不管誰均可以對其增刪改查,那麼有一些重要的數據放在list中是不安全的,因此須要一種容器類的數據類型存放重要的數據,建立之初只能查看而不能增刪改,這種數據類型就是元組。
what:這個容器型數據類型就是元組。
元組:俗稱不可變的列表,又被成爲只讀列表,元祖也是python的基本數據類型之一,用小括號括起來,裏面能夠聽任何數據類型的數據,查詢能夠,循環也能夠,切片也能夠.但就是不能改.
2.5.1 元組的索引切片
tu1 = ('a', 'b', '太白', 3, 666)
print(tu1[0]) # 'a'
print(tu1[-1]) # 666
print(tu1[1:3]) # ('b', '太白')
print(tu1[:-1]) # ('a', 'b', '太白', 3)
print(tu1[::2]) # ('a', '太白', 666)
print(tu1[::-1]) # (666, 3, '太白', 'b', 'a')
元組的索引切片
tu1 = ('a', 'b', '太白', 3, 666) print(tu1[0]) # 'a' print(tu1[-1]) # 666 print(tu1[1:3]) # ('b', '太白') print(tu1[:-1]) # ('a', 'b', '太白', 3) print(tu1[::2]) # ('a', '太白', 666) print(tu1[::-1]) # (666, 3, '太白', 'b', 'a')
2.5.2 其餘操做這些方法會在數據類型的補充時再給你們講~
2.5.2 元組其餘操做方法
由於元組的特性,直接從屬於元組的元素不能更改,因此元組只能查看。
# 能夠利用for循環查詢 tu1 = ('a', 'b', '太白', 3, 666) for i in tu1: print(i)
# 能夠利用for循環查詢 tu1 = ('a', 'b', '太白', 3, 666) for i in tu1: print(i)
index:經過元素找索引(可切片),找到第一個元素就返回,找不到該元素即報錯。
tu = ('太白', [1, 2, 3, ], 'WuSir', '女神') print(tu.index('太白')) # 0
tu = ('太白', [1, 2, 3, ], 'WuSir', '女神') print(tu.index('太白')) # 0
count: 獲取某元素在列表中出現的次數
tu = ('太白', '太白', 'WuSir', '吳超') print(tu.count('太白')) # 2
tu = ('太白', '太白', 'WuSir', '吳超') print(tu.count('太白')) # 2
2.5.3 len
tu1 = (1,2,3,4,84,5,2,8,2,11,88,2) print(len(tu1)) 結果: 12
Where:
1,就是將一些很是重要的不可以讓人改動的數據放在元組中,只供查看。
2,經常使用於元組的拆包(數據類型補充的時候會給你們講到)。
2.6.1 字典的初識
Why:我們目前已經學習到的容器型數據類型只有list,那麼list夠用?他有什麼缺點呢?
1. 列表能夠存儲大量的數據類型,可是若是數據量大的話,他的查詢速度比較慢。
2. 列表只能按照順序存儲,數據與數據之間關聯性不強。
因此針對於上的缺點,說我們須要引入另外一種容器型的數據類型,解決上面的問題,這就須要dict字典。
what:
數據類型能夠按照多種角度進行分類,就跟我們人同樣,人按照地域能夠劃分分爲亞洲人,歐洲人,美洲人等,可是按照膚色又能夠分爲白種人,黃種人,黑種人,等等,數據類型能夠按照不一樣的角度進行分類,先給你們按照可變與不可變的數據類型的分類:
不可變(可哈希)的數據類型:int,str,bool,tuple。
可變(不可哈希)的數據類型:list,dict,set。
字典是Python語言中的映射類型,他是以{}括起來,裏面的內容是以鍵值對的形式儲存的:
Key: 不可變(可哈希)的數據類型.而且鍵是惟一的,不重複的。
Value:任意數據(int,str,bool,tuple,list,dict,set),包括後面要學的實例對象等。
在Python3.5版本(包括此版本)以前,字典是無序的。
在Python3.6版本以後,字典會按照初建字典時的順序排列(即第一次插入數據的順序排序)。
固然,字典也有缺點:他的缺點就是內存消耗巨大。
字典查詢之因此快的解釋:(瞭解)
字典的查詢速度很是快,簡單解釋一下緣由:字典的鍵值對會存在一個散列表(稀疏數組)這樣的空間中,每個單位稱做一個表元,表元裏面記錄着key:value,若是你想要找到這個key對應的值,先要對這個key進行hash獲取一串數字我們簡稱爲門牌號(非內存地址),而後經過門牌號,肯定表元,對比查詢的key與被鎖定的key是否相同,若是相同,將值返回,若是不一樣,報錯。(這裏只是簡單的說一下過程,其實仍是比較複雜的。),下面我已圖形舉例:
# 此段解釋來源於《流暢的python》.
這一節籠統地描述了 Python 如何用散列表來實現 dict 類型,有些細節只是一筆帶過,像
CPython 裏的一些優化技巧 就沒有提到。可是整體來講描述是準確的。
Python 源碼 dictobject.c 模塊(http://hg.python.org/cpython/file/tip/Objects/dictobject.c)裏有豐富的註釋,另外延伸閱
讀中有對《代碼之美》一書的引用。
爲了簡單起見,這裏先集中討論 dict 的內部結構,而後再延伸到集合上面。
散列表實際上是一個稀疏數組(老是有空白元素的數組稱爲稀疏數組)。在通常的數據結構
教材中,散列表裏的單元一般叫做表元(bucket)。在 dict 的散列表當中,每一個鍵值對
都佔用一個表元,每一個表元都有兩個部分,一個是對鍵的引用,另外一個是對值的引用。因
爲全部表元的大小一致,因此能夠經過偏移量來讀取某個表元。
由於 Python 會設法保證大概還有三分之一的表元是空的,因此在快要達到這個閾值的時
候,原有的散列表會被複制到一個更大的空間裏面。
若是要把一個對象放入散列表,那麼首先要計算這個元素鍵的散列值。Python 中能夠用
hash() 方法來作這件事情,接下來會介紹這一點。
01. 散列值和相等性
內置的 hash() 方法能夠用於全部的內置類型對象。若是是自定義對象調用 hash()
的話,實際上運行的是自定義的 __hash__。若是兩個對象在比較的時候是相等的,
那它們的散列值必須相等,不然散列表就不能正常運行了。例如,若是 1 == 1.0 爲
8
真,那麼 hash(1) == hash(1.0) 也必須爲真,但其實這兩個數字(整型和浮點)
的內部結構是徹底不同的。
爲了讓散列值可以勝任散列表索引這一角色,它們必須在索引空間中儘可能分散開來。
這意味着在最理想的情況下,越是類似但不相等的對象,它們散列值的差異應該越
大。示例 3-16 是一段代碼輸出,這段代碼被用來比較散列值的二進制表達的不一樣。
注意其中 1 和 1.0 的散列值是相同的,而 1.000一、1.0002 和 1.0003 的散列值則很是不
同。
示例 3-16 在32 位的 Python 中,一、1.000一、1.0002 和 1.0003 這幾個數的散列
值的二進制表達對比(上下兩個二進制間不一樣的位被 ! 高亮出來,表格的最右
列顯示了有多少位不相同)
32-bit Python build
00000000000000000000000000000001
!= 0
1.0 00000000000000000000000000000001
------------------------------------------------
1.0 00000000000000000000000000000001
! !!! ! !! ! ! ! ! !! !!! != 16
1.0001 00101110101101010000101011011101
------------------------------------------------
1.0001 00101110101101010000101011011101
!!! !!!! !!!!! !!!!! !! ! != 20
1.0002 01011101011010100001010110111001
------------------------------------------------
1.0002 01011101011010100001010110111001
! ! ! !!! ! ! !! ! ! ! !!!! != 17
1.0003 00001100000111110010000010010110
------------------------------------------------
用來計算示例 3-16 的程序見於附錄 A。儘管程序裏大部分代碼都是用來整理輸出格
式的,考慮到完整性,我仍是把所有的代碼放在示例 A-3 中了。
從 Python 3.3 開始,str、bytes 和 datetime 對象的散列值計算過程當中多
了隨機的「加鹽」這一步。所加鹽值是 Python 進程內的一個常量,可是每次啓動
Python 解釋器都會生成一個不一樣的鹽值。隨機鹽值的加入是爲了防止 DOS 攻擊
而採起的一種安全措施。在 __hash__ 特殊方法的文檔
(https://docs.python.org/3/reference/datamodel.html#object.__hash__) 裏有相關的詳
細信息。
瞭解對象散列值相關的基本概念以後,咱們能夠深刻到散列表工做原理背後的算法
了。
02. 散列表算法
爲了獲取 my_dict[search_key] 背後的值,Python 首先會調用 hash(search_key)來計算 search_key 的散列值,把這個值最低的幾位數字看成偏移量,在散列表裏查找表元(具體取幾位,得看當前散列表的大小)。若找到的表元是空的,則拋出KeyError 異常。若不是空的,則表元裏會有一對 found_key:found_value。這時候 Python 會檢驗 search_key == found_key 是否爲真,若是它們相等的話,就會返回 found_value。若是 search_key 和 found_key 不匹配的話,這種狀況稱爲散列衝突。發生這種狀況是由於,散列表所作的實際上是把隨機的元素映射到只有幾位的數字上,而散列表自己的索引又只依賴於這個數字的一部分。爲了解決散列衝突,算法會在散列值中另外再取幾位,而後用特殊的方法處理一下,把新獲得的數字再看成索引來尋找表元。若此次找到的表元是空的,則一樣拋出 KeyError;若非空,或者鍵匹配,則返回這個值;或者又發現了散列衝突,則重複以上的步驟。圖 3-3 展現了這個算法的示意
圖。圖 3-3:從字典中取值的算法流程圖;給定一個鍵,這個算法要麼返回一個值,要麼拋出 KeyError 異常添加新元素和更新現有鍵值的操做幾乎跟上面同樣。只不過對於前者,在發現空表元的時候會放入一個新元素;對於後者,在找到相對應的表元后,原表裏的值對象會被替換成新值。
另外在插入新值時,Python 可能會按照散列表的擁擠程度來決定是否要從新分配內存爲它擴容。若是增長了散列表的大小,那散列值所佔的位數和用做索引的位數都會隨之增長,這樣作的目的是爲了減小發生散列衝突的機率。表面上看,這個算法彷佛很費事,而實際上就算 dict 裏有數百萬個元素,多數的搜索過程當中並不會有衝突發生,平均下來每次搜索可能會有一到兩次衝突。在正常狀況下,就算是最不走運的鍵所遇到的衝突的次數用一隻手也能數過來。瞭解 dict 的工做原理能讓咱們知道它的所長和所短,以及從它衍生而來的數據類型
詳細解釋
因爲字典使用了散列表,而散列表又必須是稀疏的,這致使它在空間上的效率低下。舉例而言,若是你須要存放數量巨大的記錄,那麼放在由元組或是具名元組構成的列表中會是比較好的選擇;最好不要根據 JSON 的風格,用由字典組成的列表來存放這些記錄。用元組取代字典就能節省空間的緣由有兩個:其一是避免了散列表所耗費的空間,其二是無需把記錄中字段的名字在每一個元素裏都存一遍。記住咱們如今討論的是空間優化。若是你手頭有幾百萬個對象,而你的機器有幾個GB 的內存,那麼空間的優化工做能夠等到真正須要的時候再開始計劃,由於優化每每是可維護性的對立面。
2.6.2 建立字典的幾種方式:
# 建立字典的幾種方式:
# 方式1:
dic = dict((('one', 1),('two', 2),('three', 3)))
# dic = dict([('one', 1),('two', 2),('three', 3)])
print(dic) # {'one': 1, 'two': 2, 'three': 3}
# 方式2:
dic = dict(one=1,two=2,three=3)
print(dic) # {'one': 1, 'two': 2, 'three': 3}
# 方式3:
dic = dict({'one': 1, 'two': 2, 'three': 3})
print(dic) # {'one': 1, 'two': 2, 'three': 3}
# 方式5: 後面會講到先了解
dic = dict(zip(['one', 'two', 'three'],[1, 2, 3]))
print(dic)
# 方式6: 字典推導式 後面會講到
# dic = { k: v for k,v in [('one', 1),('two', 2),('three', 3)]}
# print(dic)
# 方式7:利用fromkey後面會講到。
# dic = dict.fromkeys('abcd','太白')
# print(dic) # {'a': '太白', 'b': '太白', 'c': '太白', 'd': '太白'}
2.6.3 驗證字典的合法性
# 合法
dic = {123: 456, True: 999, "id": 1, "name": 'sylar', "age": 18, "stu": ['帥
哥', '美⼥'], (1, 2, 3): '麻花藤'}
print(dic[123])
print(dic[True])
print(dic['id'])
print(dic['stu'])
print(dic[(1, 2, 3)])
# 不合法
# dic = {[1, 2, 3]: '周杰倫'} # list是可變的. 不能做爲key
# dic = {{1: 2}: "哈哈哈"} # dict是可變的. 不能做爲key
dic = {{1, 2, 3}: '呵呵呵'} # set是可變的, 不能做爲key
2.6.4 字典的經常使用操做方法
接下來我們就進入字典的學習環節,字典對於我們小白來講可能相對於列表是很差理解的,由於列表是有序的一個一個排列的,可是字典的鍵值對對於你們來講是比較陌生的,因此我們能夠把字典比喻成一個公寓,公寓裏面有N多個房間,房間號就是鍵,房間裏面具體的東西就值:好比房間001號:對應的房間住着兩我的,也就是2person,簡稱2P,房間99號:3P, 房間78號:有人還有小動物....... 這樣,我們就能經過房間號(也就是鍵)找到對應的房間,查看裏面的內容,也就是值。
那麼首先先從字典的增刪改查開始學習。
增
# 經過鍵值對直接增長
dic = {'name': '太白', 'age': 18}
dic['weight'] = 75 # 沒有weight這個鍵,就增長鍵值對
print(dic) # {'name': '太白', 'age': 18, 'weight': 75}
dic['name'] = 'barry' # 有name這個鍵,就成了字典的改值
print(dic) # {'name': 'barry', 'age': 18, 'weight': 75}
# setdefault
dic = {'name': '太白', 'age': 18}
dic.setdefault('height',175) # 沒有height此鍵,則添加
print(dic) # {'name': '太白', 'age': 18, 'height': 175}
dic.setdefault('name','barry') # 有此鍵則不變
print(dic) # {'name': '太白', 'age': 18, 'height': 175}
#它有返回值
dic = {'name': '太白', 'age': 18}
ret = dic.setdefault('name')
print(ret) # 太白
字典的增
# 經過鍵值對直接增長 dic = {'name': '太白', 'age': 18} dic['weight'] = 75 # 沒有weight這個鍵,就增長鍵值對 print(dic) # {'name': '太白', 'age': 18, 'weight': 75} dic['name'] = 'barry' # 有name這個鍵,就成了字典的改值 print(dic) # {'name': 'barry', 'age': 18, 'weight': 75} # setdefault dic = {'name': '太白', 'age': 18} dic.setdefault('height',175) # 沒有height此鍵,則添加 print(dic) # {'name': '太白', 'age': 18, 'height': 175} dic.setdefault('name','barry') # 有此鍵則不變 print(dic) # {'name': '太白', 'age': 18, 'height': 175} #它有返回值 dic = {'name': '太白', 'age': 18} ret = dic.setdefault('name') print(ret) # 太白
刪
# pop 經過key刪除字典的鍵值對,有返回值,可設置返回值。
dic = {'name': '太白', 'age': 18}
# ret = dic.pop('name')
# print(ret,dic) # 太白 {'age': 18}
ret1 = dic.pop('n',None)
print(ret1,dic) # None {'name': '太白', 'age': 18}
#popitem 3.5版本以前,popitem爲隨機刪除,3.6以後爲刪除最後一個,有返回值
dic = {'name': '太白', 'age': 18}
ret = dic.popitem()
print(ret,dic) # ('age', 18) {'name': '太白'}
#clear 清空字典
dic = {'name': '太白', 'age': 18}
dic.clear()
print(dic) # {}
# del
# 經過鍵刪除鍵值對
dic = {'name': '太白', 'age': 18}
del dic['name']
print(dic) # {'age': 18}
#刪除整個字典
del dic
字典的刪
# pop 經過key刪除字典的鍵值對,有返回值,可設置返回值。 dic = {'name': '太白', 'age': 18} # ret = dic.pop('name') # print(ret,dic) # 太白 {'age': 18} ret1 = dic.pop('n',None) print(ret1,dic) # None {'name': '太白', 'age': 18} #popitem 3.5版本以前,popitem爲隨機刪除,3.6以後爲刪除最後一個,有返回值 dic = {'name': '太白', 'age': 18} ret = dic.popitem() print(ret,dic) # ('age', 18) {'name': '太白'} #clear 清空字典 dic = {'name': '太白', 'age': 18} dic.clear() print(dic) # {} # del # 經過鍵刪除鍵值對 dic = {'name': '太白', 'age': 18} del dic['name'] print(dic) # {'age': 18} #刪除整個字典 del dic
改
# 經過鍵值對直接改
dic = {'name': '太白', 'age': 18}
dic['name'] = 'barry'
print(dic) # {'name': 'barry', 'age': 18}
# update
dic = {'name': '太白', 'age': 18}
dic.update(sex='男', height=175)
print(dic) # {'name': '太白', 'age': 18, 'sex': '男', 'height': 175}
dic = {'name': '太白', 'age': 18}
dic.update([(1, 'a'),(2, 'b'),(3, 'c'),(4, 'd')])
print(dic) # {'name': '太白', 'age': 18, 1: 'a', 2: 'b', 3: 'c', 4: 'd'}
dic1 = {"name":"jin","age":18,"sex":"male"}
dic2 = {"name":"alex","weight":75}
dic1.update(dic2)
print(dic1) # {'name': 'alex', 'age': 18, 'sex': 'male', 'weight': 75}
print(dic2) # {'name': 'alex', 'weight': 75}
字典的改
# 經過鍵值對直接改 dic = {'name': '太白', 'age': 18} dic['name'] = 'barry' print(dic) # {'name': 'barry', 'age': 18} # update dic = {'name': '太白', 'age': 18} dic.update(sex='男', height=175) print(dic) # {'name': '太白', 'age': 18, 'sex': '男', 'height': 175} dic = {'name': '太白', 'age': 18} dic.update([(1, 'a'),(2, 'b'),(3, 'c'),(4, 'd')]) print(dic) # {'name': '太白', 'age': 18, 1: 'a', 2: 'b', 3: 'c', 4: 'd'} dic1 = {"name":"jin","age":18,"sex":"male"} dic2 = {"name":"alex","weight":75} dic1.update(dic2) print(dic1) # {'name': 'alex', 'age': 18, 'sex': 'male', 'weight': 75} print(dic2) # {'name': 'alex', 'weight': 75}
查
# 經過鍵查詢
# 直接dic[key](沒有此鍵會報錯)
dic = {'name': '太白', 'age': 18}
print(dic['name']) # 太白
# get
dic = {'name': '太白', 'age': 18}
v = dic.get('name')
print(v) # '太白'
v = dic.get('name1')
print(v) # None
v = dic.get('name2','沒有此鍵')
print(v) # 沒有此鍵
keys()
dic = {'name': '太白', 'age': 18}
print(dic.keys()) # dict_keys(['name', 'age'])
values()
dic = {'name': '太白', 'age': 18}
print(dic.values()) # dict_values(['太白', 18])
items()
dic = {'name': '太白', 'age': 18}
print(dic.items()) # dict_items([('name', '太白'), ('age', 18)])
字典的查
# 經過鍵查詢 # 直接dic[key](沒有此鍵會報錯) dic = {'name': '太白', 'age': 18} print(dic['name']) # 太白 # get dic = {'name': '太白', 'age': 18} v = dic.get('name') print(v) # '太白' v = dic.get('name1') print(v) # None v = dic.get('name2','沒有此鍵') print(v) # 沒有此鍵 keys() dic = {'name': '太白', 'age': 18} print(dic.keys()) # dict_keys(['name', 'age']) values() dic = {'name': '太白', 'age': 18} print(dic.values()) # dict_values(['太白', 18]) items() dic = {'name': '太白', 'age': 18} print(dic.items()) # dict_items([('name', '太白'), ('age', 18)])
練習題
dic = {'k1': "v1", "k2": "v2", "k3": [11,22,33]} 請在字典中添加一個鍵值對,"k4": "v4",輸出添加後的字典 請在修改字典中 "k1" 對應的值爲 "alex",輸出修改後的字典 請在k3對應的值中追加一個元素 44,輸出修改後的字典 請在k3對應的值的第 1 個位置插入個元素 18,輸出修改後的字典
fromkeys 數據類型的補充時會給你們講到~
dic = dict.fromkeys('abcd','太白') print(dic) # {'a': '太白', 'b': '太白', 'c': '太白', 'd': '太白'} dic = dict.fromkeys([1, 2, 3],'太白') print(dic) # {1: '太白', 2: '太白', 3: '太白'}
dic = dict.fromkeys('abcd','太白') print(dic) # {'a': '太白', 'b': '太白', 'c': '太白', 'd': '太白'} dic = dict.fromkeys([1, 2, 3],'太白') print(dic) # {1: '太白', 2: '太白', 3: '太白'}
其餘操做
key_list = dic.keys()
print(key_list)
結果:
dict_keys(['劍聖', '哈啥給', '大寶劍'])
# 一個高仿列表,存放的都是字典中的key
# 而且這個高仿的列表能夠轉化成列表
print(list(key_list))
# 它還能夠循環打印
dic = {'劍聖':'易','哈啥給':'劍豪','大寶劍':'蓋倫'}
for i in dic:
print(i)
value_list = dic.values()
print(value_list)
結果:
dict_values(['易', '劍豪', '蓋倫'])
#一個高仿列表,存放都是字典中的value
# 而且這個高仿的列表能夠轉化成列表
print(list(value_list))
# 它還能夠循環打印
for i in dic.values():
print(i)
key_value_list = dic.items()
print(key_value_list)
結果:
dict_items([('劍聖', '易'), ('哈啥給', '劍豪'), ('大寶劍', '蓋倫')])
# 一個高仿列表,存放是多個元祖,元祖中第一個是字典中的鍵,第二個是字典中的值
# 而且這個高仿的列表能夠轉化成列表
print(list(key_value_list ))
# 它還能夠循環打印
dic = {'劍聖':'易','哈啥給':'劍豪','大寶劍':'蓋倫'}
for i in dic.items():
print(i)
結果:
('劍聖', '易')
('哈啥給', '劍豪')
('大寶劍', '蓋倫')
key_list = dic.keys() print(key_list) 結果: dict_keys(['劍聖', '哈啥給', '大寶劍']) # 一個高仿列表,存放的都是字典中的key # 而且這個高仿的列表能夠轉化成列表 print(list(key_list)) # 它還能夠循環打印 dic = {'劍聖':'易','哈啥給':'劍豪','大寶劍':'蓋倫'} for i in dic: print(i) value_list = dic.values() print(value_list) 結果: dict_values(['易', '劍豪', '蓋倫']) #一個高仿列表,存放都是字典中的value # 而且這個高仿的列表能夠轉化成列表 print(list(value_list)) # 它還能夠循環打印 for i in dic.values(): print(i) key_value_list = dic.items() print(key_value_list) 結果: dict_items([('劍聖', '易'), ('哈啥給', '劍豪'), ('大寶劍', '蓋倫')]) # 一個高仿列表,存放是多個元祖,元祖中第一個是字典中的鍵,第二個是字典中的值 # 而且這個高仿的列表能夠轉化成列表 print(list(key_value_list )) # 它還能夠循環打印 dic = {'劍聖':'易','哈啥給':'劍豪','大寶劍':'蓋倫'} for i in dic.items(): print(i) 結果: ('劍聖', '易') ('哈啥給', '劍豪') ('大寶劍', '蓋倫')
這裏補充一個知識點:分別賦值,也叫拆包。
a,b = 1,2
print(a,b)
結果:
2
a,b = ('你好','世界') # 這個用專業名詞就叫作元組的拆包
print(a,b)
結果:
你好 世界
a,b = ['你好','大飛哥']
print(a,b)
結果:
你好 世界
a,b = {'汪峯':'北京北京','王菲':'天后'}
print(a,b)
結果:
汪峯 王菲
a,b = 1,2 print(a,b) 結果: 1 2 a,b = ('你好','世界') # 這個用專業名詞就叫作元組的拆包 print(a,b) 結果: 你好 世界 a,b = ['你好','大飛哥'] print(a,b) 結果: 你好 世界 a,b = {'汪峯':'北京北京','王菲':'天后'} print(a,b) 結果: 汪峯 王菲
因此利用上面剛學的拆包的概念,咱們循環字典時還能夠這樣獲取字典的鍵,以及值:
for k,v in dic.items():
print('這是鍵',k)
print('這是值',v)
結果:
這是鍵 劍聖
這是值 易
這是鍵 哈啥給
這是值 劍豪
這是鍵 大寶劍
這是值 蓋倫
for k,v in dic.items(): print('這是鍵',k) print('這是值',v) 結果: 這是鍵 劍聖 這是值 易 這是鍵 哈啥給 這是值 劍豪 這是鍵 大寶劍 這是值 蓋倫
4.1.5字典的嵌套
字典的嵌套是很是重要的知識點,這個必需要創建在熟練使用字典的增刪改查的基礎上,並且字典的嵌套纔是我們在工做中常常會遇到的字典,工做中遇到的字典不是簡簡單單一層,而就像是蔥頭同樣,一層接一層,但通常都是頗有規律的嵌套,那麼接下來咱們就學習一下字典的嵌套:
如今有以下字典,完成一下需求:
dic = {
'name':'汪峯',
'age':48,
'wife':[{'name':'國際章','age':38}],
'children':{'girl_first':'小蘋果','girl_second':'小怡','girl_three':'頂頂'}
}
1. 獲取汪峯的名字。
2.獲取這個字典:{'name':'國際章','age':38}。
3. 獲取汪峯妻子的名字。
4. 獲取汪峯的第三個孩子名字。
dic = { 'name':'汪峯', 'age':48, 'wife':[{'name':'國際章','age':38}], 'children':{'girl_first':'小蘋果','girl_second':'小怡','girl_three':'頂頂'} } 1. 獲取汪峯的名字。 2.獲取這個字典:{'name':'國際章','age':38}。 3. 獲取汪峯妻子的名字。 4. 獲取汪峯的第三個孩子名字。
解題思路:
1.獲取汪峯的名字。: 這個比較簡單,汪峯就是dic的一個鍵對應的值,咱們經過這個key就能夠獲取到汪峯這個值。
name = dic['name'] print(name)
name = dic['name'] print(name)
2. 獲取這個字典{'name':'國際章','age':38}: 想要獲取這個字典,先要看字典從屬於誰?這個字典從屬於一個列表,而這個列表是字典wife對應的鍵,因此我們應該先經過wife獲取到對應的這個列表,而後經過這個列表按照因此取值取到對應的這個字典。
l1 = dic['wife'] # 先獲取到這個列表
di = l1[0] # 列表按照索引取值,這個字典是列表的第一個元素,因此經過索引獲取到這個字典
print(di)
# 固然上面是分佈獲取的,咱們還能夠合併去寫:
di = dic['wife'][0]
print(di)
l1 = dic['wife'] # 先獲取到這個列表 di = l1[0] # 列表按照索引取值,這個字典是列表的第一個元素,因此經過索引獲取到這個字典 print(di) # 固然上面是分佈獲取的,咱們還能夠合併去寫: di = dic['wife'][0] print(di)
3. 獲取汪峯的妻子名字: 仍是按照上一題的思路:想要獲取汪峯妻子的名字:國際章,那麼他是一個字典的鍵對應的值,因此咱們經過'name'這個鍵就能夠獲取到對應的值,這個題的難點是獲取到這個小字典,而上一個題咱們已經獲取了這個小字典,因此在上面的基礎上再執行就能夠了。
di = dic['wife'][0] # 這個是上一次題獲取的小字典的代碼
wife_name= di['name'] # 經過小字典而後再經過鍵就能獲取到對應的值
print(wife_name)
# 固然我們能夠簡化:
wife_name = dic['wife'][0]['name]
print(wife_name)
di = dic['wife'][0] # 這個是上一次題獲取的小字典的代碼 wife_name= di['name'] # 經過小字典而後再經過鍵就能獲取到對應的值 print(wife_name) # 固然我們能夠簡化: wife_name = dic['wife'][0]['name] print(wife_name)
4. 獲取汪峯的第三個孩子名字: 汪峯的孩子們是在一個字典中的,你要想獲取汪峯的第三個孩子,你應該先獲取到它從屬於的這個字典,而後再經過這個字典獲取第三個孩子的名字。
dic2 = dic['children'] # 先獲取這個字典
name = dic2['girl_three'] # 在經過這個字典獲取第三個孩子的名字
print(name)
# 固然你能夠簡化:
name = dic['children']['girl_three']
print(name)
dic2 = dic['children'] # 先獲取這個字典 name = dic2['girl_three'] # 在經過這個字典獲取第三個孩子的名字 print(name) # 固然你能夠簡化: name = dic['children']['girl_three'] print(name)
dic1 = {
'name':['alex',2,3,5],
'job':'teacher',
'oldboy':{'alex':['python1','python2',100]}
}
1,將name對應的列表追加⼀個元素’wusir’。
2,將name對應的列表中的alex⾸字⺟⼤寫。
3,oldboy對應的字典加⼀個鍵值對’⽼男孩’,’linux’。
4,將oldboy對應的字典中的alex對應的列表中的python2刪除
相關練習題
dic1 = { 'name':['alex',2,3,5], 'job':'teacher', 'oldboy':{'alex':['python1','python2',100]} } 1,將name對應的列表追加⼀個元素’wusir’。 2,將name對應的列表中的alex⾸字⺟⼤寫。 3,oldboy對應的字典加⼀個鍵值對’⽼男孩’,’linux’。 4,將oldboy對應的字典中的alex對應的列表中的python2刪除
集合是無序的,不重複的數據集合,它裏面的元素是可哈希的(不可變類型),可是集合自己是不可哈希(因此集合作不了字典的鍵)的。如下是集合最重要的兩點:
去重,把一個列表變成集合,就自動去重了。
關係測試,測試兩組數據以前的交集、差集、並集等關係。
1,集合的建立。
set1 = set({1,2,'barry'}) set2 = {1,2,'barry'} print(set1,set2) # {1, 2, 'barry'} {1, 2, 'barry'}
2,集合的增。
set1 = {'alex','wusir','ritian','egon','barry'} set1.add('景女神') print(set1) #update:迭代着增長 set1.update('A') print(set1) set1.update('老師') print(set1) set1.update([1,2,3]) print(set1)
3,集合的刪。
set1 = {'alex','wusir','ritian','egon','barry'} set1.remove('alex') # 刪除一個元素 print(set1) set1.pop() # 隨機刪除一個元素 print(set1) set1.clear() # 清空集合 print(set1) del set1 # 刪除集合 print(set1)
4,集合的其餘操做:
4.1 交集。(& 或者 intersection)
set1 = {1,2,3,4,5} set2 = {4,5,6,7,8} print(set1 & set2) # {4, 5} print(set1.intersection(set2)) # {4, 5}
4.2 並集。(| 或者 union)
set1 = {1,2,3,4,5} set2 = {4,5,6,7,8} print(set1 | set2) # {1, 2, 3, 4, 5, 6, 7,8}
print(set2.union(set1)) # {1, 2, 3, 4, 5, 6, 7,8}
4.3 差集。(- 或者 difference)
set1 = {1,2,3,4,5} set2 = {4,5,6,7,8} print(set1 - set2) # {1, 2, 3} print(set1.difference(set2)) # {1, 2, 3}
4.4反交集。 (^ 或者 symmetric_difference)
set1 = {1,2,3,4,5} set2 = {4,5,6,7,8} print(set1 ^ set2) # {1, 2, 3, 6, 7, 8} print(set1.symmetric_difference(set2)) # {1, 2, 3, 6, 7, 8}
4.5子集與超集
set1 = {1,2,3} set2 = {1,2,3,4,5,6} print(set1 < set2) print(set1.issubset(set2)) # 這兩個相同,都是說明set1是set2子集。 print(set2 > set1) print(set2.issuperset(set1)) # 這兩個相同,都是說明set2是set1超集。
5,frozenset不可變集合,讓集合變成不可變類型。
s = frozenset('barry') print(s,type(s)) # frozenset({'a', 'y', 'b', 'r'}) <class 'frozenset'>
for循環:用戶按照順序循環可迭代對象的內容。
msg = '老男孩python是全國範圍內最好的python培訓機構' for item in msg: print(item) li = ['alex','銀角','女神','egon','太白'] for i in li: print(i) dic = {'name':'太白','age':18,'sex':'man'} for k,v in dic.items(): print(k,v)
enumerate:枚舉,對於一個可迭代的(iterable)/可遍歷的對象(如列表、字符串),enumerate將其組成一個索引序列,利用它能夠同時得到索引和值。
li = ['alex','銀角','女神','egon','太白'] for i in enumerate(li): print(i) for index,name in enumerate(li,1): print(index,name) for index, name in enumerate(li, 100): # 起始位置默認是0,可更改 print(index, name)
range:指定範圍,生成指定數字。
for i in range(1,10): print(i) for i in range(1,10,2): # 步長 print(i) for i in range(10,1,-2): # 反向步長 print(i)
l1 = ['wusir', 'alex', '太白', '女神', 12, 666] for i in range(len(l1)): print(i)