一.什么是數據類型?
什么是數據類型?
我們人類可以很容易的分清數字與字符的區別,但是計算機並不能呀,計算機雖然很強大,但從某種角度上看又很傻,除非你明確的告訴它,1是數字,“漢”是文字,否則它是分不清1和‘漢’的區別的,因此,在每個編程語言里都會有一個叫數據類型的東東,其實就是對常用的各種數據類型進行了明確的划分,你想讓計算機進行數值運算,你就傳數字給它,你想讓他處理文字,就傳字符串類型給他。Python中常用的數據類型有多種,如下:
整數(int) ,字符串(str),布爾值(bool),列表(list),元組(tuple),字典(dict),集合(set).
- int。數字:主要用於運算。1 ,2,3...
- bool。判斷真假:True, False.
- str。簡單少量的儲存數據,並進行相應的操作。name = 'alex',
- tuple。只讀,不能更改。(1,'alex')
- list:大量有序數據,[1,'ses',True,[1,2,3],{'name':'jinxin'}]
- dict:大量數據,且是關聯性比較強的數據 {'name':'jinxin','age':18,'name_list':['張三','李四']}
二.基礎數據類型。
2.1數字int。
nt,就是咱們常見的數據類型,主要是用於葛總運算,加減乘數等這里就不給你舉例說明了。
首先要給大家講下是十進制與二進制之間的轉換。
2.1.1 十進制二進制轉換
十進制整數轉換為二進制整數采用"除2取余,逆序排列"法。具體做法是:用2整除十進制整數,可以得到一個商和余數;再用2去除商,又會得到一個商和余數,如此進行,直到商為小於1時為止,然后把先得到的余數作為二進制數的低位有效位,后得到的余數作為二進制數的高位有效位,依次排列起來。
十進制小數轉換成二進制小數采用"乘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
2.2布爾值bool。
布爾值就兩種: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'
2.3字符串str。
Python中凡是用引號引起來的數據可以稱為字符串類型,組成字符串的每個元素稱之為字符,將這些字符一個一個連接起來,然后在用引號起來就是字符串。
s1 = '太白nb' # 對於s1這個字符串來說,它由四個字符組成:太, 白, n, b。
2.3.1、字符串的索引與切片。
組成字符串的字符從左至右,依次排列,他們都是有順序的,就好比是部隊的隊列,從左至右依次報號(從零開始) :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.2、字符串常用方法。
字符串除了可以用切片(步長)之外,還有一些其他的操作方法。

#數字符串中的元素出現的個數。 # 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)
2.4列表list
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.5、其他操作
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]

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:(這個知識點用在什么地方):
你需要存儲大量的數據,且需要這些數據有序的時候。
制定一些特殊的數據群體:按順序,按規則,自定制設計數據。
2.5元組tuple。
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')
2.5.2 其他操作這些方法會在數據類型的補充時再給大家講~
2.5.2 元組其他操作方法
因為元組的特性,直接從屬於元組的元素不能更改,所以元組只能查看。

# 可以利用for循環查詢 tu1 = ('a', 'b', '太白', 3, 666) for i in tu1: print(i)
index:通過元素找索引(可切片),找到第一個元素就返回,找不到該元素即報錯。

tu = ('太白', [1, 2, 3, ], 'WuSir', '女神') print(tu.index('太白')) # 0
count: 獲取某元素在列表中出現的次數

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字典dict。
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 8 真,那么 hash(1) == hash(1.0) 也必須為真,但其實這兩個數字(整型和浮點) 的內部結構是完全不一樣的。 為了讓散列值能夠勝任散列表索引這一角色,它們必須在索引空間中盡量分散開來。 這意味着在最理想的狀況下,越是相似但不相等的對象,它們散列值的差別應該越 大。示例 3-16 是一段代碼輸出,這段代碼被用來比較散列值的二進制表達的不同。 注意其中 1 和 1.0 的散列值是相同的,而 1.0001、1.0002 和 1.0003 的散列值則非常不 同。 示例 3-16 在32 位的 Python 中,1、1.0001、1.0002 和 1.0003 這幾個數的散列 值的二進制表達對比(上下兩個二進制間不同的位被 ! 高亮出來,表格的最右 列顯示了有多少位不相同) 32-bit Python build 1 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) # 太白
刪

# 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[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: '太白'}
其他操作

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) 結果: 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) 結果: 這是鍵 劍聖 這是值 易 這是鍵 哈啥給 這是值 劍豪 這是鍵 大寶劍 這是值 蓋倫
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. 獲取汪峰的第三個孩子名字。
解題思路:
1.獲取汪峰的名字。: 這個比較簡單,汪峰就是dic的一個鍵對應的值,我們通過這個key就可以獲取到汪峰這個值。

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)
3. 獲取汪峰的妻子名字: 還是按照上一題的思路:想要獲取汪峰妻子的名字:國際章,那么他是一個字典的鍵對應的值,所以我們通過'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)

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刪除
2.7集合set (了解)
集合是無序的,不重復的數據集合,它里面的元素是可哈希的(不可變類型),但是集合本身是不可哈希(所以集合做不了字典的鍵)的。以下是集合最重要的兩點:
去重,把一個列表變成集合,就自動去重了。
關系測試,測試兩組數據之前的交集、差集、並集等關系。
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,enumerate,range)。
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)