目錄
标簽:python
目錄:
計算機内部使用二進制表示資料。
1位
二進制可以代表
2種
狀态,
n位
二進制可以表示
2^n種
狀态,一般使用如下圖示來計算一個位元組的二進制和十進制互轉:
128 64 32 16 8 4 2 1
256 1 1 1 1 1 1 1 1
78 0 1 0 0 1 1 1 0
33 0 0 1 0 0 0 0 1
6 0 0 0 0 0 1 1 0
不論是文字、圖檔、視訊還是其他類型的資料,在
計算機内部
都是以
二進制
的形式存儲和表示。對于文字類型的資料,二進制需要通過文字編碼表的映射關系,将二進制資料轉換為對應的文字。文字編碼表預先收錄了
字形
和
二進制資料
的對應關系。但不同的國家因文字不同,是以産生了不同的編碼表,編碼表也叫作編碼格式。
因不同國家的文字不同,各國都編寫了适合本國語言的編碼格式。如
GBK
是中國的編碼格式,
ASCII
是美國的編碼格式,
SHIFT_JIS
是日本的編碼格式等等。不同的編碼格式給出了不同的二進制和字形的對應關系标準,是以不同編碼格式之間不能混用,否則會出現亂碼。
正因為編碼格式互相不相容,國際标準組織才出面編寫了一個全球各國通用的
unicode
編碼格式,此編碼格式将全世界的語言都囊括進去,不論是哪一個國家,隻要使用unicode進行編碼,輸出的檔案都可以在全球通用,是以unicode也稱為:萬國碼。(當然,讀取的時候也要使用unicode編碼進行讀取)
但是,unicode編碼格式要求一個字元至少對應2個位元組的二進制資料,這就導緻對于編碼長度小于2個位元組的語言比如英文來說,存儲空間加倍,不但影響存儲,還影響傳輸效率。
此時
UTF-8
編碼格式應運而生,UTF-8在unicode基礎上,使用可變長編碼的方法,使用1-4個位元組來表示一個字元,優先使用1位元組,不夠的話再增加1位元組,以此類推。通過變長的方式用于優化unicode在存儲和傳輸時帶來的資源浪費。
簡單來說,python3在記憶體中操作字元串時的編碼格式統一是unicode,而在讀寫檔案時使用的編碼格式預設是UTF-8。
python中的浮點數包括:
有限小數
(如:
1.2
)和
無限循環小數
1/3
)。
python中的浮點數精度最長隻有小數點後16位,可以使用decimal子產品來提高精度。使用python3的/運算得到的結果就是浮點數。此外,浮點數還用于
科學計數法
,如
1000000
的科學計數法寫法是:
1.0E6
。
當超出浮點數目前精度的時候會發生
四舍五入
的操作。
清單可以簡單的被了解成一個
存儲容器
。此容器可以存放不同種類的對象,可以新增一個對象、删除一個對象、或者替換一個對象。清單類似于數組,隻不過python的清單是
動态
的,不僅可以動态擴充和縮小長度,還可以存放不同的資料類型。清單使用如下方式聲明:
li = [0,1,2,3,4]
或者
li = list(range(5))
1. 查詢
li[0]或者li[-1] # 通過下标索引對象值,不能超出下标範圍
li.index('a') # 通過對象值查找對應下标,不存在的對象會導緻此函數報錯ValueError
li.count('a') # 得到清單中'a'值出現的次數
2. 增加
li.append(20) # 在清單末尾追加元素
li.insert(0, 20) # 在清單下标0出插入20,這會導緻元素右側統一右移一個機關
3. 修改
li[0] = 20 # 直接修改第一個元素的值為20
li[:3] = [1,2,3] # 将清單前三個元素批量修改
4. 删除
li.remove(23) # 根據元素值删除元素,不存在會報錯ValueError
li.pop(0) # 根據元素下标删除元素,不給于參數則預設-1
del li[1] # 使用通用删除關鍵字del
del li[1:5] # 使用del批量删除
5. 切片
li = [1,2,3,4,5]
L = li[:3] # L的值是[1,2,3],切片含首不含尾
L = li[:] # 将li清單進行淺複制賦予L
L = li[::-1] # 将li清單倒序後淺複制賦予L
6. 更新/擴充
list_a.extend(list_b) # 将b的值更新至a
list_a = [1,2]
list_b = [2,3]
list_a.extend(list_b) # a的值是[1,2,3],b保持不變
7. 拼接
list_a = [1,2]
list_b = [2,3]
list_c = list_a + list_c # c的值是[1,2,3],a和b保持不變
8. 排序
li.sort() # 在原始清單上修改,排序預設方式是升序
li.reverse() # 讓清單倒序
9. 循環
for i in li:
print(i)
10. 清空/複制
li.clear()
list_b = list_a.copy() # 等價于list_b = list_a[:]
因為清單是可變對象,即清單中的元素是可以改變的,是以在複制清單的時候,如果使用簡單的複制(即淺複制),遇到嵌套的小清單時就會出現問題。為了規避可變對象在修改值時的安全問題,對于可變對象的複制,建議使用深複制。深複制的使用方式如下:
import copy
list1 = [1,2,3,[4,5],6]
list2 = copy.deepcopy(list1)
list1[-2][-1] = 'abc'
print(list1)
print(list2)
結果是:
[1, 2, 3, [4, 'abc'], 6]
[1, 2, 3, [4, 5], 6]
字元串就是一串字元序列,字元串在計算機中也是二進制資料,這些二進制資料通過編碼格式顯示成對應的字形,即字元串。字元串是不可變對象,一旦被建立就無法被修改。
1.判斷是否是數字字元串
str.isdigit()
s = '123'
s.isdigit() # 值是True
s = '123b'
s.isdigit() # 值是False
2. 替換字元
str2 = str1.replace(old, new) # 傳回一個新字元串
s1 = 'aaahello,world'
s2 = s1.replace('a', 'A')
print(s1)
print(s2)
結果:
aaahello,world
AAAhello,world
3. 定位字元
i = str.index(char) # 不存在會報錯
i = str.find(char) # 不存在傳回-1
s1 = 'aaahello world'
print(s1.index('a'))
print(s1.index('b'))
print(s1.find('a'))
print(s1.find('b'))
結果:
0
報錯ValueError
0
-1
4. 字元計數
count = str.count(char) # 查找字元串中char字元的個數
s1 = 'aaahello world'
print(s1.count('a'))
結果:
3
5. 處理首尾空格
str2 = str1.strip() # 傳回新字元串,删除首尾空格
s1 = ' hello world'
print(s1)
print(s1.strip())
結果:
hello world
hello world
6. 處理banner展示條
str2 = str1.center(len, char) # 使用char填充字元串長度到len
s1 = 'student info'
print(s1.center(20, '*'))
print(s1.center(20, '-'))
print(s1.center(20, '+'))
結果:
****student info****
----student info----
++++student info++++
7. 分割字元串産生清單
list = str.split(char) # 根據char字元分割字元串成清單,預設cahr是空格
s1 = 'student!info!xiaoming'
li = s1.split('!')
print(type(li))
print(li)
結果:
<class 'list'>
['student', 'info', 'xiaoming']
8. 拼接字元串清單成更長字元串
str = char.join(list) # 根據char字元連接配接list裡的所有字元串成為更長的字元串
li = ['student', 'info', 'xiaoming']
s1 = '+'.join(li)
print(type(s1))
print(s1)
結果:
<class 'str'>
student+info+xiaoming
9. 字元串格式化輸出
str2 = str1.format(*args, **kw) # 根據args和kw來對應指派
result = 'name:{name}, age:{age}, a {0},a {1}'.format('apple', 'bananer', name='xiaoming', age=26)
print(result)
結果:
name:xiaoming, age:26, a apple,a bananer
10. 判斷字元串開頭和結尾
bool = str.startwith/endwith(char) # 判斷是否以char開頭或結尾
s1 = 'hello'
s2 = 'world'
print(s1.startswith('h'))
print(s2.endswith('d'))
結果:
True
True
11. 改變字元串大小寫
str2 = str1.upper/lower() # 設定大小寫
s1 = 'hello world'
print(s1.upper())
結果:
HELLO WORLD
在字元串前面增加一個r可以取消此字元串在print過程中的轉義功能,進而列印出字元串字面量。
s1 = '\ta\nbc'
print(s1)
s2 = r'\tabc\n'
print(s2)
結果:
a
bc
\tabc\n
元組可以認為是隻讀清單,元組的操作大部分和清單一緻,隻不過一旦定義完畢之後就不能修改元組元素的值。
但是,如果元組元素是一個可變對象比如清單,則可以修改此清單中的值,這并不違反元組的規則因為清單自身這個容器的記憶體位址并沒有變化。
tu = (1,2,[3,4])
# tu[0] = 10 # 這條語句會報錯
tu[-1].append(5)
print(tu)
結果是:
(1, 2, [3, 4, 5])
- 哈希函數用于将任意長度的輸入通過算法計算得到固定長度的輸出,這個輸出也叫哈希值。
- 雜湊演算法是根據輸入值的特征計算的,是以如果輸入值不停變化,則輸出也會不穩定,這就要求輸入的是不可變對象。
- 因為雜湊演算法的原因,可能會出現不同的輸入值有同樣的輸出值,這就發生了哈希沖突,是以想通過輸出來反推唯一的輸入是不合理的。
- 資料中儲存的使用者密碼都是密文。
- 使用哈希的程式一定要有處理沖突的子產品。
字典在某種角度上和清單很類似,都可以被認為是存儲工具,儲存各種資料類型對象。不過清單是通過下标索引,而字典是通過key來索引。另外,清單是有序的,而字典是無序的,因為字典的key涉及到雜湊演算法的計算。
資料類型 | 是否有序 | 索引值 | 作用 | 是否可變對象 | 使用方式 |
---|---|---|---|---|---|
清單 | 有序 | 下标,從0開始 | 存儲其他對象位址 | 是 | li[0],li[-1] |
字典 | 無序 | key值,不可變對象 | dic[key] |
1. 增加
字典沒有追加的函數,增加一個key-value的方式是直接:
dic['name'] = 'xiaoming'
如果dic中已經存在'name'的key,則會使用'xiaoming'來覆寫原有的value
2. 修改
字典的修改直接是:
dic['name'] = new_value
将新的值覆寫原有值
3. 查找
方法1:print(dic['name'])
如果dic沒有'name'的key,則會報錯
方法2:print(dic.get('name', 'not found!')
如果dic沒有'name'的key,則會傳回'not found!',預設第二參數是None,可以不填寫
方法1:del dic['name']
如果dic沒有'name'的key,則會報錯
方法2:dic.pop('name', 'not found!')
如果dic沒有'name'的key,則會傳回'not found!',第二參數沒有預設值,必須手工輸入否則會報錯
5. 清空/複制
dic.clear()
dic2 = dic1.copy() # 淺複制
6. 設定預設
dic.setdefault('name', 'xiaoming')
首先,dic會查找自身是否有'name',如果有傳回原有value值。如果沒有,就新增這個key-value并傳回新value值。
7. 更新
dic1.update(dic2)
使用dic2來更新dic1,有則覆寫,無則新增。
dic1 = {
'a': 1,
'b': 2,
'x': 3,{'a': 1, 'b': 2, 'x': 100, 'y': 200}
}
dic2 = {
'b': 2,
'x': 100,
'y': 200,
}
dic1.update(dic2)
print(dic1)
結果是:
{'a': 1,
'b': 2,
'x': 100,
'y': 200
}
8. fromkeys
為一系列key設定統一的value值,并傳回此字典。比如要為3個房地産樓盤設定統一價格:
dic = dict.fromkeys(['萬科', '陽光城', '融信'], 2000)
print(dic)
結果是:
{'萬科': 2000, '陽光城': 2000, '融信': 2000}
9. 循環擷取keys、values、items
for key in dic.keys()
for value in dic.values()
for item in dic.items()
集合一般用于分類計算。集合中的元素都是唯一的,不會有重複。集合是無序的,集合是可變對象,但是集合内的元素必須是不可變對象。因為集合一般用于分類計算,是站在集合次元的,是以集合并不支援s[0]這種方式來通路元素。
s = {1,2,3,4,5}
print(s.pop()) # 随機删除一個元素
s.add(50)
s.add(60)
print(s)
s.discard(100) # 删除元素,不存在不會報錯
# s.remove(100) # 100不存在就會報錯
s2 = {100,200,300}
s.update(s2) # 兩個集合合并,其實就是并集
print(s)
s.clear() # 清空集合元素
print(s)
結果是:
1
{2, 3, 4, 5, 50, 60}
{2, 3, 4, 5, 100, 200, 300, 50, 60}
set() # 代表空集合
s1 = {11,22,33}
s2 = {22,33,44}
print('交集是:', s1 & s2) # 交集是: {33, 22}
print('s1 對于 s2 的差集是:', s1 - s2) # s1 對于 s2 的差集是: {11}
print('s2 對于 s1 的差集是:', s2 - s1) # s2 對于 s1 的差集是: {44}
print('并集是:', s1 | s2) # 并集是: {33, 11, 44, 22}
print('對稱差集是:', s1 ^ s2) # 對稱差集是: {11, 44}
print('s1是s2的超集嗎?', s1.issuperset(s2), s1 > s2) # s1是s2的超集嗎? False False
print('s1是s2的子集嗎?', s1.issubset(s2), s1 < s2) # s1是s2的子集嗎? False False
print('23在不在是s1中?', 23 in s1) # 23在不在是s1中? False
print('s1 和 s2 是不是 不相交?', s1.isdisjoint(s2)) # s1 和 s2 是不是 不相交? False
這裡從:python3讀取檔案abc.txt,執行檔案中的代碼并在指令行展現内容的整個過程來了解各環節的編碼問題。
檔案準備
# abc.txt
str1 = '中國'
print(str1)
環境準備
python環境:python3.6.1
os環境:windows 10
abc.txt是使用pycharm編輯的,pycharm的編碼設定為UTF-8
開始
- 我們登入
作業系統,windows作業系統預設的編碼格式是windows
,windows中有一個GBK
指令行,此指令行的編碼格式繼承了作業系統的格式,也是cmd
GBK
- 打開
,預設pycharm在安裝完畢後的編碼格式是GBK,可以通過設定修改為UTF-8。pycharm
- 在pycharm中建立檔案
,在此檔案中寫入:abc.txt
str1 = '中國'
print(str1)
- 注意,此時abc.txt檔案中的
的編碼格式是str1
,即編輯器pycharm是什麼格式,則編寫的檔案就是什麼編碼格式。UTF-8
- 使用
儲存此檔案到硬碟。Crtl+s
- 單獨在
中打開cmd
解釋器,進入python
,在互動環境中,我們可以輸入:互動環境
s1 = 'hello world'
s2 = '你好 世界'
不論你輸入的是什麼字元串,不論是
中文
還是
英文
,此時在python3互動環境中的編碼格式都是統一的
unicode
- 退出python3互動環境,在cmd指令中通過指令啟動
解釋器執行abc.txt檔案:python3
第7步其實有很多小環節:python abc.txt
- python3會使用
的讀寫檔案的編碼格式對abc.txt檔案進行解釋。python3預設讀寫編碼格式是
預設
,而此檔案恰好也是以
UTF-8
格式儲存在硬碟上的,是以python3可以正确的對此檔案進行編碼。
UTF-8
- python3通過UTF-8讀寫檔案編碼對此檔案進行解釋,将UTF-8的檔案内容轉換成
格式的字元串保留在
unicode
中。
記憶體
- python3解釋器執行unicode的儲存在記憶體中的代碼,設定一個
變量,建立一個
str1
格式的
unicode
'中國'
- python3執行
函數,此時
依然是
str1
格式
unicode
- print函數被執行,
的
str1
會被列印到cmd中
'中國'
指令行接收到一個以
cmd
編碼的字元串,雖然cmd預設是
unicode
編碼,但是cmd可以認識
GBK
GBK
,是以可以根據unicode編碼規則列印出此字元串的字形:
unicode
'中國'
總之,有如下幾個環節是需要編碼的:
- python3解釋器内部編碼,也就是在記憶體中的編碼格式,就是unicode
- python3解釋器去讀取檔案時使用的編碼格式,預設是UTF-8,會按照你在檔案頭部指定的# coding: xxx來設定,不設定的話就是UTF-8
- 檔案自身也有一個編碼格式,此編碼格式來源于編輯此檔案的編輯器
- 編輯器的編碼格式繼承了作業系統的編碼格式,mac/Linux是UTF-8,windows是GBK,此外,cmd和shell也繼承了作業系統的編碼格式
a = [1]
if a:
print('true')
else:
print('false')
這裡的if條件是判斷成立的,但是如下兩者卻是false:
a == True
a is True
為什麼?
首先,a和True不能用is比較,因為是肯定不同的兩個對象記憶體位址。也不能用==比較因為是不同的資料類型,值是肯定不同的。其次,if a這個語句等價于:if boo(a),bool(a)的結果是True,是以可以判斷成立。
dic = {
'a': 1,
'b': 2,
'c': 3,
}
for key in dic.keys():
print(key, dic[key])
for key, value in dic.items():
print(key, value)
哪一種循環的性能更好?
嘗試過兩種辦法:
- 兩種循環各循環100次,計算運作時間,發現是下面那種時間短。
-
擴大dic的資料量到100萬個項目,兩種循環各執行1次,發現上面那種時間短。
目前還不知道确切分析的方法,後續補充。
用處:需要判斷while是否完全正常執行完畢時
i = 0
while i < 10:
print(i)
i += 1
else:
print('循環正常執行完畢,沒有被break或者return打斷')