上節課內容回顧 1. 字典 {key:value, key:value.....} 成對的保存數據 字典沒有索引. 不能切片, 字典的key必須是可哈希的.不可變的 1. 增長: dic[新key] = 值 dic.setdefault(key, value) 新增, 查詢 2. 修改: dic[老key] = 值 dic.update(d) 把d更新到dic中 3. 刪除; pop(key) popitem() 隨機刪除 del dic[key] clear() 清空 4. 查詢 for k in dic: k dic[k] get(key) 若是key不存在, 返回None dic[key] 若是key不存在, 報錯 setdefault(key, value) 根據key查詢出value 5. 相關操做 1. keys() 全部的key 2. values() 全部的value 3. items() 全部的key和value for k, v in dic.items(): # 自動解包 k v set集合 內部元素必須可哈希. 不可變 內部元素不重複 add() 添加 frozenset() 凍結集合. 不可變的.(##通常的集合自己是可變的,可是要求其內部的元素是不可變的,而這個集合自己就是不可變的)
今日主要內容 1. 小數據池, id() 小數據池針對的是: int, str, bool 在py文件中幾乎全部的字符串都會緩存. id() 查看變量的內存地址 2. is和==的區別 is 比較的是內存地址 == 比較的是內容 當兩個變量指向同一個對象的時候. is是True, ==也是True 3. 再談編碼 回顧: 1. ascii. 有: 數字, 字母, 特殊字符. 8bit 1byte 128 最前面是0 2. gbk. 包含: ascii, 中文(主要), 日文, 韓文, 繁體文字. 16bit, 2byte. 3. unicode. 包含gbk,ascii,big5... 32bit, 4byte 4. utf-8. 可變長度的unicode. 1. 英文: 8bit,1byte 2. 歐洲文字: 16bit 2byte 3. 中文: 24bit 3byte 不一樣的編碼之間不能隨意轉換. 中國人gbk和德國人utf-8罵 想要溝通必須經過英文(unicode)(媒介) 在python3中. 默認的編碼是unicode,咱們的字符串就是unicode 在python2中. 默認的編碼是ASCII. Cpython是用 c 語言寫的,c語言的默認編碼是ASCII unicode弊端:在存儲和傳輸的時候. 是很浪費的 在存儲和傳輸的時候不能直接使用unicode. 必需要對字符串進行編碼. 編碼成bytes類型 bytes: 字節形式的字符串 1. encode(編碼格式) 編碼 2. decode(編碼格式) 解碼 bytes是一種另類的字符串表示形式 "哈哈哈" => \xee\xab\x13\xee\xab\x13\xee\xab\x13
在說小數據池以前.咱們先看一個概念.什麼是代碼塊:html
根據提示咱們從官方文檔找到了這樣的說法: A Python program is constructed from code blocks. A block is a piece of Python program text that is executed as a unit. The following are blocks: a module,a function body, and a class definition. Each command typed interactively is a block. A script file (a file given as standard input to the interpreter or specified as a command line argument to the interpreter) is a code block. A script command (a command specified on the interpreter command line with the‘-C‘ option) is a code bLock. The string argument passed to the built-in functions evalO and execO) is a code block. A code block is executed in an execution frame. A frame contains some admi ni strative information (used for debugging) and determines where and how execution continues after the code bLock's execution has compLeted. 粗略的翻譯: python程序是由代碼塊構成的.一個代碼塊的文本做爲python程序執行的單元. 代碼塊:一個模塊,一個函數,一個類,甚至每個command命令都是一個代碼塊.一個文件也是一個代碼塊,evalO)和exec( )執行的時候也是一個代碼塊
什麼是命令行?
咱們在控制檯CMD中輸入python進入的就是python的command模式.在這裏也能夠寫
python的程序.
而根據上面的官方的解釋來看.一個command命令就是一個python代碼塊python
接下來咱們來看一下小數據池is和==的區別編程
# id()函數能夠幫咱們查看一個變量的內存地址 a = 10 b = 30 print(id(a)) # 1515545088 print(id(b)) # 1515545728 lst = ['周杰倫', "麻花藤"] print(id(lst)) # 166167624 print(lst) lst = [] # 建立了一個新列表 lst.append("胡辣湯") print(id(lst)) # 166167624 print(lst) lst1 = [1,2,3] # 兩個對象 內存地址是不同的 lst2 = [1,2,3] print(id(lst1)) # 166167624 print(id(lst2)) # 166122376 s1 = "abc" # 內存中是沒有"abc", 建立一個新的 0.0001 s2 = "abc" # 內存中是已經有了"abc", 直接把abc拿來用 0.0000001 print(id(s1), id(s2)) # 31096032 31096032 # 使用頻率最高的數據類型: 字符串,爲了可以快速的建立字符串. # 節省內存. 把相同的規律的字符串進行緩存,當下次建立的時候就不在建立了 # 把字符串的緩存-> 小數據池 -> String iterning -> 常量池 -> 字符串緩存 # 在建立字符串以前. 先去小數據池對比. 是否已經存在了該字符串.若是存在了. # 就不建立新的了. 直接拿原來存在的數據, 省略掉反覆重複建立字符串的過程. 節約內存 # 什麼數據會被緩存 # 數字, 字符串, 布爾值 => 都是不可變的數據類型 # 1. 數字 a = 1000 b = 1000 print(id(a), id(b)) # 165830000 165830000 # 2. 字符串. 若是單純的寫字符串. 幾乎都會被緩存 s1 = "a昨天上廁所沒關門. 紅衝進去了. 麪筋歌出來了. 有故事a昨天上廁所沒關門. 紅衝進去了. 麪筋歌出來了. 有故事a昨天上廁所沒關門. 紅衝進去了. 麪筋歌出來了. 有故事" s2 = "a昨天上廁所沒關門. 紅衝進去了. 麪筋歌出來了. 有故事a昨天上廁所沒關門. 紅衝進去了. 麪筋歌出來了. 有故事a昨天上廁所沒關門. 紅衝進去了. 麪筋歌出來了. 有故事" print(id(s1), id(s2)) # 31222064 31222064 # 若是在py文件中寫的字符串. 幾乎都是緩存的 # 在黑窗口裏的寫的幾乎都不會緩存 # 不一樣的解釋器. 緩存的機制也不同 # # 優勢: 能夠幫咱們快速的建立對象.節省內存. # 缺點: 緩存若是過大. 響應速度會比較慢 # 不要糾結. # == 和 is 區別: # # == 比較的是數據, 外貌 # is 比較的是內存地址, 比較身份證號 lst1 = [1,2,3] lst2 = [1,2,3] # 列表沒有小數據池 print(id(lst1), id(lst2)) # 166167560 166126408 print(lst1 == lst2) # True print(lst1 is lst2) # False s1 = "我叫周潤發" s2 = "我叫周潤發" print(s1 == s2) print(s1 is s2) # 小數據池 tu1 = ("週一", "週二") tu2 = ("週一", "週二") print(tu1 is tu2) # 地址不相等 False print(tu1 == tu2) # 內容相等 True # == 比較的是內容 # is 比較內存地址
經過id()咱們能夠查看到一個變量表示的值在內存中的地址.緩存
s = 'alex' print(id(s)) # 4326667072
==判斷左右兩端的值是否相等.是否是一致.
is判斷左右兩端內容的內存地址是否一致. 若是返回True,那能夠肯定這兩個變量使用的是同一個對象網絡
咱們能夠這樣認爲. 若是內存地址相同,那麼值必定是相等的. 若是值相等, 則不必定是同一 個對象.app
小數據池,一種數據緩存機制,也被稱爲駐留機制.各大編程語言中都有相似的末西.在網上搜索常量池,小數據池指的都是同一個內容.
小數據池只針対:整數,字符串,布尓値.其餘的數據類型不存在駐留機制編程語言
#對於整數,Python官方文檔中這麼說: The current implementation keeps an array of integer objects for all integers between -5 and 256,
when you create an int in that range you actually just get back a reference to the existing object.
So it should be possible to change the value of 1. I suspect the behaviour of Python in this case is undefined. #對於字符串: Incomputer science, string interning is a method of storing only onecopy of each distinct string value,
which must be immutable. Interning strings makes some stringprocessing tasks more time- or space-efficient
at the cost of requiring moretime when the string is created or interned. The distinct values are stored ina string intern pool. –引⾃維基百科
在python中對-5到256之間的整數會被駐留在內存中,將必定規則的字符串緩存.在使用的時候,內存中只會建立一個該數據的對象,保存在小數據池中.當使用的時候直接從小數據池中獲取對象的內存引用,而不須要建立一個新的數據,這樣會節省更多的內存區域.
優勢:可以提升一些字符串,整數的處理速度.省略掉建立對象的過程.
缺點:在'池'中建立或者插入新的內容會花費更多的時間.ide
#對於數字: -5~256是會被加到小數據池中的,每次使用都是同一個對象. #對於字符串: 1.若是字符串的長度是0或者1,都會默認進行緩存 (也要是在同一個代碼塊中) 2.字符串長度大於1,可是字符串中只包含字母,數字,下劃線時纔會緩存 3.用乘法獲得的字符串 ①.乘數爲1,僅包含數字,字母,下劃線時會被緩存.若是包含其餘字符,而長度<=1也會被駐存. ②.乘數大於1,僅包含數字,字母,下劃線這個時候會被緩存.但字符串長度不能大於20 4.指定駐留.咱們能夠經過sys模塊中的intern()函數來指定要駐留的內容.
OK.到目前爲止.咱們已經瞭解了python的小數據池的一些基本狀況了.可是!!還有最後一個問題.小數據池和最開始的代碼塊有什麼關係呢?
一樣的一段代碼在命令行窗口和在py文件中.出現的效果是徹底不同的.函數
a = 1000 b = 1000 print(a is b) 注意. 在py文件中,獲得的結果是True, 可是在command(命令行)中就是False了.
在代碼塊內的緩存機制是不同的.在執行同一個代碼塊的初始化對象的命令時,會檢查是否其值是否已經存在,若是存在,會將其重用.換句話說:執行同一個代碼塊時,遇到初始化對象的命令時,他會將初始化的這個變量與值存儲在一個字典中,在遇到新的變量時,會先在字典中查詢記錄,若是有一樣的記錄那麼它會重複使用這個字典中的以前的這個值.因此在你給出的例子中,文件執行時(同一個代碼塊)會把a, b兩個變量指向同一個對象.若是是不一樣的代碼塊,他就會看這個兩個變量是不是知足小數據池的數據,若是是知足小數據池的數據則會指向同一個地址.因此: a, b的賦值語句分別被看成兩個代碼塊執行,可是他們不知足小數據池的數據因此會獲得兩個不一樣的對象,於是is判斷返回False.ui
s = "我今天很是的困" # 21個utf-8 bs = s.encode("gbk") # 把字符串轉化成utf-8格式bytes # bytes不是給人看的. 給機器用的 # 14個字節 gbk # b'\xce\xd2\xbd\xf1\xcc\xec\xb7\xc7\xb3\xa3\xb5\xc4\xc0\xa7' # 21個字節 utf-8 # b'\xe6\x88\x91\xe4\xbb\x8a\xe5\xa4\xa9\xe9\x9d\x9e\xe5\xb8\xb8\xe7\x9a\x84\xe5\x9b\xb0' print(bs) # utf-8和gbk是不能直接轉換的, 必須使用unicode來轉換 bs = b'\xe6\x88\x91\xe4\xbb\x8a\xe5\xa4\xa9\xe9\x9d\x9e\xe5\xb8\xb8\xe7\x9a\x84\xe5\x9b\xb0' # 把字節轉化回字符串 s = bs.decode("utf-8") print(s) b'\xe6\x88\x91\xe4\xbb\x8a\xe5\xa4\xa9\xe9\x9d\x9e\xe5\xb8\xb8\xe7\x9a\x84\xe5\x9b\xb0' # 把這個bytes轉化成gbk的bytes bs = b'\xe6\x88\x91\xe4\xbb\x8a\xe5\xa4\xa9\xe9\x9d\x9e\xe5\xb8\xb8\xe7\x9a\x84\xe5\x9b\xb0' # 解碼 s = bs.decode("utf-8") print(s) # 編碼 bss = s.encode("gbk") print(bss) # 關於bytes, 非ascii中的內容. 展現的時候都是\x.. 若是是ascii中的內容. 原樣輸出 name = "alex昨天吃多了" bs = name.encode("gbk") # b'alex\xd7\xf2\xcc\xec\xb3\xd4\xb6\xe0\xc1\xcb' print(bs) bss = name.encode("utf-8") # b'alex\xe6\x98\xa8\xe5\xa4\xa9\xe5\x90\x83\xe5\xa4\x9a\xe4\xba\x86' print(bss)
1. python2中默認使用的是ASCII碼,因此不支持中文.若是須要在Python2中更改編碼須要在文件的開始編寫:
# -*- encoding:utf-8 -*-
2. python3中: 內存中使用的是unicode碼.
#編碼回顧: 1. ASCII: 最先的編碼.裏面有英文大寫字母,小寫字母,數字,一些特殊字符. 沒有中文,8個01代碼, 8個bit, 1個byte 2. GBK:中文國標碼,裏面包含了ASCII編碼和中文經常使用編碼.16個bit, 2個byte 3. UNICODE: 萬國碼,裏面包含了全世界全部國家文字的編碼.32個bit, 4個byte,包含了ASCII 4. UTF-8:可變長度的萬國碼.是unicode的一種實現.最小字符佔8位 1.英文: 8bit 1byte 2.歐洲文字:16bit 2byte 3.中文: 24bit 3byte 綜上,除了ASCII碼之外,其餘信息不能直接轉換.要經過Unicode轉換
在python3的內存中,在程序運行階段使用的是unicode編碼.由於unicode是萬國碼,什麼內容均可以進行顯示.那麼在數據傳輸和存儲的時候因爲unicode比較浪費空間和資源.須要把unicode轉存成UTF-8或者GBK進行存儲.怎麼轉換呢.在python中能夠把文字信息進行編碼,編碼以後的內容就能夠進行傳輸了,編碼以後的數據是bytes類型的數據.其實啊,仍是原來的數據只是通過編碼以後表現形式發生了改變而已.
bytes的表現形式:
1.英文b'alex' 英文的表現形式和字符串沒什麼兩樣 2.中文b"\xe4\xb8\xad' 這是一個漢字的UTF-8的bytes表現形式
字符串在傳輸時轉化成bytes=> encode(字符集)來完成
s = "alex" print(s.encode("utf-8")) #將字符串編碼成UTF-8 print(s.encode("GBK")) #將字符串編碼成GBK #結果: b'alex' b'alex' s = "中" print(s.encode("UTF-8")) #中文編碼成UTF-8 print(s.encode("GBK")) # 中文編碼成GBK #結果: b'\xe4\xb8\xad' b'\xd6\xd0'
記住:英文編碼以後的結果和源字符串一致.中文編碼以後的結果根據編碼的不一樣,編碼結果也不一樣.咱們能看到,一箇中文的UTF-8編碼是3個字節,一個GBK的中文編碼是2個字節.
編碼以後的類型就是bytes類型.在網絡傳輸和存儲的時候咱們python是保存和存儲的bytes類型.那麼在對方接收的時候,也是接收的bytes類型的數據.
咱們可使用decode0來進行解碼操做.把bytes類型的數據還原回咱們熟悉的字符串:
s = "我叫李嘉誠" print(s.encode("utf-8")) # b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a' print(b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'.decod e("utf-8")) # 解碼
編碼和解碼的時候都須要制定編碼格式.
s = "我是文字" bs = s.encode("GBK") # 咱們這樣能夠獲取到GBK的文字 # 把GBK轉換成UTF-8 # 首先要把GBK轉換成unicode. 也就是須要解碼 s = bs.decode("GBK") # 解碼成unicode # 而後須要進⾏從新編碼成UTF-8 bss = s.encode("UTF-8") # 從新編碼 print(bss)
Python2和Python3的比較:
- 字符串和字節不一樣 py2: name=u"alex"(用unicode進行編碼) name='alex'(utf-8/gbk/ascii) unicode(就是py3中的str類型) str(就是py3中的bytes類型)
py3: name='alex'(用unicode進行編碼) name=b'alex'(utf-8/gbk/ascii)
str bytes