一、字符串(str)
1.1 字符串的定義
- 字符串 就是 一串字符,是編程語(yǔ)言中表示文本的數(shù)據(jù)類(lèi)型
- 在 Python 中可以使用 一對(duì)雙引號(hào) " 或者 一對(duì)單引號(hào) ' 定義一個(gè)字符串
- 可以使用?索引?獲取一個(gè)字符串中?指定位置的字符,索引計(jì)數(shù)從?0?開(kāi)始
- 也可以使用 for 循環(huán)遍歷 字符串中每一個(gè)字符
1
#
!/usr/bin/env python3
2
#
-*-coding:utf-8-*-
3
4
"""
5
@author:fyh
6
@time:2019/5/31
7
"""
8
9
str1 =
"
hello python
"
10
11
for
c
in
str1:
12
print
(c, end=
'
\t
'
)
13
14
#
運(yùn)行結(jié)果:h e l l o p y t h o n
1.2 字符串的常用操作
1
#
!/usr/bin/env python3
2
#
-*-coding:utf-8-*-
3
4
"""
5
@author:fyh
6
@time:2019/5/31
7
"""
8
9
#
1 * 重復(fù)輸出字符串
10
print
(
'
hello
'
* 2
)
11
12
#
2 [] ,[:] 通過(guò)索引獲取字符串中字符
13
print
(
'
helloworld
'
[2
:])
14
15
#
3 in 成員運(yùn)算符 - 如果字符串中包含給定的字符返回 True
16
print
(
'
el
'
in
'
hello
'
)
17
18
#
4 % 格式字符串
19
print
(
'
alex is a good teacher
'
)
20
print
(
'
%s is a good teacher
'
%
'
alex
'
)
21
22
#
5 + 字符串拼接
23
a =
'
123
'
24
b =
'
abc
'
25
c =
'
789
'
26
d1 = a + b +
c
27
print
(d1)
#
+效率低,該用join
28
29
#
join效率高
30
d2 =
''
.join([a, b, c])
31
print
(d2)
1.3 字符串相關(guān)的函數(shù)
#
string.upper() 轉(zhuǎn)換 string 中的小寫(xiě)字母為大寫(xiě)
#
string.lower() 轉(zhuǎn)換 string 中所有大寫(xiě)字符為小寫(xiě)
#
string.startswith(obj, beg=0,end=len(string)) 檢查字符串是否是以obj開(kāi)頭,是則返回True,否則返回 False。如果beg 和 end 指定值,則在指定范圍內(nèi)檢查.
#
string.endswith(obj, beg=0, end=len(string)) 檢查字符串是否以 obj 結(jié)束,如果beg 或者 end 指定則檢查指定的范圍內(nèi)是否以 obj 結(jié)束,如果是,返回 True,否則返回 False.
#
string.replace(str1, str2, num=string.count(str1)) 把 string 中的 str1 替換成 str2,如果 num 指定,則替換不超過(guò) num 次.
#
string.strip([obj]) 在 string 上執(zhí)行 lstrip()和 rstrip() 去除空格
#
string.split(str="", num=string.count(str)) 以 str 為分隔符切片 string,如果 num有指定值,則僅分隔 num 個(gè)子字符串
#
string.find(str, beg=0, end=len(string)) 檢測(cè) str 是否包含在 string 中,如果 beg 和 end 指定范圍,則檢查是否包含在指定范圍內(nèi),如果是返回開(kāi)始的索引值,否則返回-1
#
string.encode(encoding='UTF-8', errors='strict') 以 encoding 指定的編碼格式編碼 string,如果出錯(cuò)默認(rèn)報(bào)一個(gè)ValueError 的異常,除非 errors 指定的是ignore或者replace
#
string.decode(encoding='UTF-8', errors='strict') 以 encoding 指定的編碼格式解碼 string,如果出錯(cuò)默認(rèn)報(bào)一個(gè)ValueError的異常,除非errors指定的是'ignore'或 者'replace'
#
string.join(seq) 以 string 作為分隔符,將 seq 中所有的元素(的字符串表示)合并為一個(gè)新的字符串
#
string.format() 格式化輸出
#
string.capitalize() 把字符串的第一個(gè)字符大寫(xiě)
#
string.center(width) 返回一個(gè)原字符串居中,并使用空格填充至長(zhǎng)度 width 的新字符串
#
string.count(str, beg=0, end=len(string)) 返回 str 在 string 里面出現(xiàn)的次數(shù),如果 beg 或者 end 指定則返回指定范圍內(nèi) str 出現(xiàn)的次數(shù)
#
string.expandtabs(tabsize=8) 把字符串 string 中的 tab 符號(hào)轉(zhuǎn)為空格,tab 符號(hào)默認(rèn)的空格數(shù)是8。
#
string.index(str, beg=0, end=len(string)) 跟find()方法一樣,只不過(guò)如果str不在 string中會(huì)報(bào)一個(gè)異常.
#
string.isalnum() 如果 string 至少有一個(gè)字符并且所有字符都是字母或數(shù)字則返回 True,否則返回 False
#
string.isalpha() 如果 string 至少有一個(gè)字符并且所有字符都是字母則返回 True,否則返回 False
#
string.isdecimal() 如果 string 只包含十進(jìn)制數(shù)字則返回 True 否則返回 False.
#
string.isdigit() 如果 string 只包含數(shù)字則返回 True 否則返回 False.
#
string.islower() 如果 string 中包含至少一個(gè)區(qū)分大小寫(xiě)的字符,并且所有這些(區(qū)分大小寫(xiě)的)字符都是小寫(xiě),則返回 True,否則返回 False
#
string.isnumeric() 如果 string 中只包含數(shù)字字符,則返回 True,否則返回 False
#
string.isspace() 如果 string 中只包含空格,則返回 True,否則返回 False.
#
string.istitle() 如果 string 是標(biāo)題化的(見(jiàn) title())則返回 True,否則返回 False
#
string.isupper() 如果 string 中包含至少一個(gè)區(qū)分大小寫(xiě)的字符,并且所有這些(區(qū)分大小寫(xiě)的)字符都是大寫(xiě),則返回 True,否則返回 False
#
string.ljust(width) 返回一個(gè)原字符串左對(duì)齊,并使用空格填充至長(zhǎng)度 width 的新字符串
#
string.lstrip() 截掉 string 左邊的空格
#
string.maketrans(intab, outtab]) maketrans() 方法用于創(chuàng)建字符映射的轉(zhuǎn)換表,對(duì)于接受兩個(gè)參數(shù)的最簡(jiǎn)單的調(diào)用方式,第一個(gè)參數(shù)是字符串,表示需要轉(zhuǎn)換的字符,第二個(gè)參數(shù)也是字符串表示轉(zhuǎn)換的目標(biāo)。
#
max(str) 返回字符串 str 中最大的字母。
#
min(str) 返回字符串 str 中最小的字母。
#
string.partition(str) 有點(diǎn)像 find()和 split()的結(jié)合體,從 str 出現(xiàn)的第一個(gè)位置起,把 字 符 串 string 分 成 一 個(gè) 3 元 素 的 元 組 (string_pre_str,str,string_post_str),如果 string 中不包含str 則 string_pre_str == string.
#
string.rfind(str, beg=0,end=len(string) ) 類(lèi)似于 find()函數(shù),不過(guò)是從右邊開(kāi)始查找.
#
string.rindex( str, beg=0,end=len(string)) 類(lèi)似于 index(),不過(guò)是從右邊開(kāi)始.
#
string.rjust(width) 返回一個(gè)原字符串右對(duì)齊,并使用空格填充至長(zhǎng)度 width 的新字符串
#
string.rpartition(str) 類(lèi)似于 partition()函數(shù),不過(guò)是從右邊開(kāi)始查找.
#
string.rstrip() 刪除 string 字符串末尾的空格.
#
string.splitlines(num=string.count('\n')) 按照行分隔,返回一個(gè)包含各行作為元素的列表,如果 num 指定則僅切片 num 個(gè)行.
#
string.swapcase() 翻轉(zhuǎn) string 中的大小寫(xiě)
#
string.title() 返回"標(biāo)題化"的 string,就是說(shuō)所有單詞都是以大寫(xiě)開(kāi)始,其余字母均為小寫(xiě)(見(jiàn) istitle())
#
string.translate(str, del="") 根據(jù) str 給出的表(包含 256 個(gè)字符)轉(zhuǎn)換 string 的字符,要過(guò)濾掉的字符放到 del 參數(shù)中
1
#
!/usr/bin/env python3
2
#
-*-coding:utf-8-*-
3
4
"""
5
@author:fyh
6
@time:2019/5/31
7
"""
8
9
name =
"
hello world
"
10
#
小寫(xiě)字母變?yōu)榇髮?xiě)
11
print
(name.upper())
#
HELLO WORLD
12
print
(name)
#
hello world
13
14
#
把大寫(xiě)字母變小寫(xiě)
15
name2 =
"
HELLO WORLD
"
16
print
(name2.lower())
#
hello world
17
print
(name2)
#
HELLO WORLD
18
19
#
判斷是否以。。。開(kāi)頭
20
name3 =
"
hello
"
21
print
(name3.startswith(
"
he
"
))
#
True
22
#
檢查字符串是否以。。結(jié)尾
23
print
(name3.endswith(
"
lo
"
))
#
True
24
25
#
replace 替換
26
name4 =
"
python
"
27
print
(name4.replace(
'
th
'
,
'
aa
'
))
#
pyaaon
28
29
#
去除空格
30
name5 =
"
bbcc
"
31
print
(name5.strip())
#
bbcc
32
33
#
分割
34
str1 =
"
aa|bb|cc|dd
"
35
print
(str1.split(
'
|
'
))
#
['aa', 'bb', 'cc', 'dd']
36
37
#
查找 返回開(kāi)始的索引值
38
str2 =
"
we are family
"
39
print
(str2.find(
"
are
"
))
#
3
40
41
#
join 拼接
42
lst1 = [
'
aa
'
,
'
bb
'
,
'
cc
'
,
'
dd
'
]
43
print
(
"
-
"
.join(lst1))
#
aa-bb-cc-dd
1.4 字符串切片
- 切片 使用 索引值 來(lái)限定范圍,根據(jù) 步長(zhǎng) 從原序列中 取出一部分 元素組成新序列
- 切片 方法適用于 字符串、列表、元組
-
切片的語(yǔ)法表達(dá)式為:[start_index : end_index : step],其中:
- start_index:起始索引
- end_index:結(jié)束索引
- step:步長(zhǎng)
1
#
!/usr/bin/env python3
2
#
-*-coding:utf-8-*-
3
4
"""
5
@author:fyh
6
@time:2019/5/31
7
"""
8
9
str1 =
"
hello world
"
10
11
12
print
(str1[1:6
])
13
#
結(jié)果是ello
14
15
print
(str1[1:6:2
])
16
#
結(jié)果是el
17
18
print
(str1[2
:])
19
#
結(jié)果是llo world
20
#
保留start_index,但省略end_index,這樣會(huì)從起始索引開(kāi)始,切到最后一個(gè)元素為止
21
22
print
(str1[:5
])
23
#
結(jié)果是hello
24
#
省略start_index,保留end_index,這樣會(huì)從第一個(gè)元素開(kāi)始,切到end_index - 1的元素為止
25
26
print
(str1[-1:-6:-1
])
27
#
結(jié)果是dlrow
28
29
print
(str1[1:6:-1
])
30
#
結(jié)果為空
31
#
切片時(shí),一定要保證start_index到end_index的方向與步長(zhǎng)step的方向同向,否則會(huì)切出空的序列
1.5 字符串拼接
Python的字符串格式化有三種方式:?百分號(hào)方式、format方式、f-strings方式
1.5.1 百分號(hào)方式
格式:%[(name)][flags][width].[precision]typecode
-
(name) ? ? ?可選,用于選擇指定的key
-
flags ? ? ? ? ?可選,可供選擇的值有:
-
+ ? ? ? 右對(duì)齊;正數(shù)前加正好,負(fù)數(shù)前加負(fù)號(hào);
-
- ? ? ? ?左對(duì)齊;正數(shù)前無(wú)符號(hào),負(fù)數(shù)前加負(fù)號(hào);
-
空格 ? ?右對(duì)齊;正數(shù)前加空格,負(fù)數(shù)前加負(fù)號(hào);
-
0 ? ? ? ?右對(duì)齊;正數(shù)前無(wú)符號(hào),負(fù)數(shù)前加負(fù)號(hào);用0填充空白處
-
width ? ? ? ? 可選,占有寬度
-
precision ? 可選,小數(shù)點(diǎn)后保留的位數(shù)
-
typecode ? ?必選
-
s,獲取傳入對(duì)象的__str__方法的返回值,并將其格式化到指定位置
-
r,獲取傳入對(duì)象的__repr__方法的返回值,并將其格式化到指定位置
-
c,整數(shù):將數(shù)字轉(zhuǎn)換成其unicode對(duì)應(yīng)的值,10進(jìn)制范圍為?0 <= i <= 1114111(py27則只支持0-255);字符:將字符添加到指定位置
-
o,將整數(shù)轉(zhuǎn)換成 八進(jìn)制表示,并將其格式化到指定位置
-
x,將整數(shù)轉(zhuǎn)換成十六進(jìn)制表示,并將其格式化到指定位置
-
d,將整數(shù)、浮點(diǎn)數(shù)轉(zhuǎn)換成 十 進(jìn)制表示,并將其格式化到指定位置
-
e,將整數(shù)、浮點(diǎn)數(shù)轉(zhuǎn)換成科學(xué)計(jì)數(shù)法,并將其格式化到指定位置(小寫(xiě)e)
-
E,將整數(shù)、浮點(diǎn)數(shù)轉(zhuǎn)換成科學(xué)計(jì)數(shù)法,并將其格式化到指定位置(大寫(xiě)E)
-
f, 將整數(shù)、浮點(diǎn)數(shù)轉(zhuǎn)換成浮點(diǎn)數(shù)表示,并將其格式化到指定位置(默認(rèn)保留小數(shù)點(diǎn)后6位)
-
F,同上
-
g,自動(dòng)調(diào)整將整數(shù)、浮點(diǎn)數(shù)轉(zhuǎn)換成 浮點(diǎn)型或科學(xué)計(jì)數(shù)法表示(超過(guò)6位數(shù)用科學(xué)計(jì)數(shù)法),并將其格式化到指定位置(如果是科學(xué)計(jì)數(shù)則是e;)
-
G,自動(dòng)調(diào)整將整數(shù)、浮點(diǎn)數(shù)轉(zhuǎn)換成浮點(diǎn)型或科學(xué)計(jì)數(shù)法表示(超過(guò)6位數(shù)用科學(xué)計(jì)數(shù)法),并將其格式化到指定位置(如果是科學(xué)計(jì)數(shù)則是E;)
-
%,當(dāng)字符串中存在格式化標(biāo)志時(shí),需要用 %%表示一個(gè)百分號(hào)
注:Python中百分號(hào)格式化是不存在自動(dòng)將整數(shù)轉(zhuǎn)換成二進(jìn)制表示的方式
常用的格式化:
1
tpl =
"
i am %s
"
%
"
alex
"
2
3
tpl =
"
i am %s age %d
"
% (
"
alex
"
, 18
)
4
5
tpl =
"
i am %(name)s age %(age)d
"
% {
"
name
"
:
"
alex
"
,
"
age
"
: 18
}
6
7
tpl =
"
percent %.2f
"
% 99.97623
8
9
tpl =
"
i am %(pp).2f
"
% {
"
pp
"
: 123.425556
, }
10
11
tpl =
"
i am %.2f %%
"
% 123.425556
1.5.2 format方式
格式:[[fill]align][sign][#][0][width][,][.precision][type]
-
fill? ? ? ? ? 【可選】空白處填充的字符
-
align? ? ? 【可選】對(duì)齊方式(需配合width使用)
-
<,內(nèi)容左對(duì)齊
-
>,內(nèi)容右對(duì)齊(默認(rèn))
-
=,內(nèi)容右對(duì)齊,將符號(hào)放置在填充字符的左側(cè),且只對(duì)數(shù)字類(lèi)型有效。 即使:符號(hào)+填充物+數(shù)字
-
^,內(nèi)容居中
-
sign ? ? ? ? 【可選】有無(wú)符號(hào)數(shù)字
-
+,正號(hào)加正,負(fù)號(hào)加負(fù);
-
?-,正號(hào)不變,負(fù)號(hào)加負(fù);
-
空格 ,正號(hào)空格,負(fù)號(hào)加負(fù);
-
# ? ? ? ? ? ?【可選】對(duì)于二進(jìn)制、八進(jìn)制、十六進(jìn)制,如果加上#,會(huì)顯示 0b/0o/0x,否則不顯示
-
, ? ? ? ? ? ?【可選】為數(shù)字添加分隔符,如:1,000,000
-
width ? ? ? 【可選】格式化位所占寬度
-
.precision 【可選】小數(shù)位保留精度
-
type ? ? ? ? 【可選】格式化類(lèi)型
-
傳入” 字符串類(lèi)型 “的參數(shù)
-
s,格式化字符串類(lèi)型數(shù)據(jù)
-
空白,未指定類(lèi)型,則默認(rèn)是None,同s
-
傳入“ 整數(shù)類(lèi)型 ”的參數(shù)
-
b,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換成2進(jìn)制表示然后格式化
-
c,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換為其對(duì)應(yīng)的unicode字符
-
d,十進(jìn)制整數(shù)
-
o,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換成8進(jìn)制表示然后格式化;
-
x,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換成16進(jìn)制表示然后格式化(小寫(xiě)x)
-
X,將10進(jìn)制整數(shù)自動(dòng)轉(zhuǎn)換成16進(jìn)制表示然后格式化(大寫(xiě)X)
-
-
- 傳入“ 浮點(diǎn)型或小數(shù)類(lèi)型?”的參數(shù)
-
-
-
e, 轉(zhuǎn)換為科學(xué)計(jì)數(shù)法(小寫(xiě)e)表示,然后格式化;
-
E, 轉(zhuǎn)換為科學(xué)計(jì)數(shù)法(大寫(xiě)E)表示,然后格式化;
-
f , 轉(zhuǎn)換為浮點(diǎn)型(默認(rèn)小數(shù)點(diǎn)后保留6位)表示,然后格式化;
-
F, 轉(zhuǎn)換為浮點(diǎn)型(默認(rèn)小數(shù)點(diǎn)后保留6位)表示,然后格式化;
-
g, 自動(dòng)在e和f中切換
-
G, 自動(dòng)在E和F中切換
-
%,顯示百分比(默認(rèn)顯示小數(shù)點(diǎn)后6位)
-
常用的格式化:
1
tpl =
"
i am {}, age {}, {}
"
.format(
"
seven
"
, 18,
'
alex
'
)
2
3
tpl =
"
i am {}, age {}, {}
"
.format(*[
"
seven
"
, 18,
'
alex
'
])
4
5
tpl =
"
i am {0}, age {1}, really {0}
"
.format(
"
seven
"
, 18
)
6
7
tpl =
"
i am {0}, age {1}, really {0}
"
.format(*[
"
seven
"
, 18
])
8
9
tpl =
"
i am {name}, age {age}, really {name}
"
.format(name=
"
seven
"
, age=18
)
10
11
tpl =
"
i am {name}, age {age}, really {name}
"
.format(**{
"
name
"
:
"
seven
"
,
"
age
"
: 18
})
12
13
tpl =
"
i am {0[0]}, age {0[1]}, really {0[2]}
"
.format([1, 2, 3], [11, 22, 33
])
14
15
tpl =
"
i am {:s}, age {:d}, money {:f}
"
.format(
"
seven
"
, 18, 88888.1
)
16
17
tpl =
"
i am {:s}, age {:d}
"
.format(*[
"
seven
"
, 18
])
18
19
tpl =
"
i am {name:s}, age {age:d}
"
.format(name=
"
seven
"
, age=18
)
20
21
tpl =
"
i am {name:s}, age {age:d}
"
.format(**{
"
name
"
:
"
seven
"
,
"
age
"
: 18
})
22
23
tpl =
"
numbers: {:b},{:o},{:d},{:x},{:X}, {:%}
"
.format(15, 15, 15, 15, 15, 15.87623, 2
)
24
25
tpl =
"
numbers: {:b},{:o},{:d},{:x},{:X}, {:%}
"
.format(15, 15, 15, 15, 15, 15.87623, 2
)
26
27
tpl =
"
numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}
"
.format(15
)
28
29
tpl =
"
numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}
"
.format(num=15)
1.5.3 f-strings
f-strings 提供一種簡(jiǎn)潔易讀的方式, 可以在字符串中包含 Python 表達(dá)式. f-strings 以字母 'f' 或 'F' 為前綴, 格式化字符串使用一對(duì)單引號(hào)、雙引號(hào)、三單引號(hào)、三雙引號(hào). 格式化字符串中。
1
#
!/usr/bin/env python
2
#
-*-coding:utf-8-*-
3
4
"""
5
@author:fyh
6
@time:2019/6/5
7
"""
8
name =
'
豪仔
'
9
age = 26
10
format_string1 = f
'
我的名字是 {name}, 我的年齡是 {age}
'
11
print
(format_string1)
#
我的名字是 豪仔, 我的年齡是 26
12
13
format_string2 = f
"
我的名字是 {name}, 我的年齡是 {age}
"
14
print
(format_string2)
#
我的名字是 豪仔, 我的年齡是 26
15
16
format_string3 = F
'''
我的名字是 {name}, 我的年齡是 {age}
'''
17
print
(format_string3)
#
我的名字是 豪仔, 我的年齡是 26
18
19
format_string4 = F
"""
我的名字是 {name}, 我的年齡是 {age}
"""
20
print
(format_string4)
#
我的名字是 豪仔, 我的年齡是 26
21
22
#
花括號(hào)中的數(shù)字會(huì)先運(yùn)算
23
format_string5 = f
'
3 + 5 = {3 + 5}
'
24
print
(format_string5)
#
3 + 5 = 8
25
26
a = 10
27
b = 20
28
format_string6 = f
'
3 + 5 = {a + b}
'
29
print
(format_string6)
#
3 + 5 = 30
30
31
#
兩個(gè)花括號(hào)會(huì)被替換為一個(gè)花括號(hào), 注意{{}} 不表示表達(dá)式
32
format_string7 = F
'
我的名字是 {{name}}, 我的年齡是 {{age}}
'
33
print
(format_string7)
?
二、bytes
Python3最重要的新特性之一是對(duì)字符串和二進(jìn)制數(shù)據(jù)流做了明確的區(qū)分。文本總是Unicode,由str類(lèi)型表示,二進(jìn)制數(shù)據(jù)則由bytes類(lèi)型表示。Python3不會(huì)以任意隱式的方式混用str和bytes,你不能拼接字符串和字節(jié)流,也無(wú)法在字節(jié)流里搜索字符串(反之亦然),也不能將字符串傳入?yún)?shù)為字節(jié)流的函數(shù)(反之亦然)。
2.1 回顧編碼的發(fā)展史
在計(jì)算機(jī)歷史的早期,美國(guó)為代表的英語(yǔ)系國(guó)家主導(dǎo)了整個(gè)計(jì)算機(jī)行業(yè),26個(gè)英文字母組成了多樣的英語(yǔ)單詞、語(yǔ)句、文章。因此,最早的字符編碼規(guī)范是ASCII碼,一種8位即1個(gè)字節(jié)的編碼規(guī)范,它可以涵蓋整個(gè)英語(yǔ)系的編碼需要。
編碼是什么?編碼就是把一個(gè)字符用一個(gè)二進(jìn)制來(lái)表示。我們都知道,所有的東西,不管是英文、中文還是符號(hào)等等,最終存儲(chǔ)在磁盤(pán)上都是01010101這類(lèi)東西。在計(jì)算機(jī)內(nèi)部,讀取和存儲(chǔ)數(shù)據(jù)歸根結(jié)底,處理的都是0和1組成的比特流。問(wèn)題來(lái)了,人類(lèi)看不懂這些比特流,如何讓這些010101對(duì)人類(lèi)變得可讀呢?于是出現(xiàn)了字符編碼,它是個(gè)翻譯機(jī),在計(jì)算機(jī)內(nèi)部某個(gè)地方,透明的幫我們將比特流翻譯成人類(lèi)可以直接理解的文字。對(duì)于一般用戶(hù),不需要知道這個(gè)過(guò)程是什么原理,是怎么執(zhí)行的。但是對(duì)于程序員卻是個(gè)必須搞清楚的問(wèn)題。
以ASCII編碼為例,它規(guī)定1個(gè)字節(jié)8個(gè)比特位代表1個(gè)字符的編碼,也就是“00000000”這么寬,一個(gè)一個(gè)字節(jié)的解讀。例如:01000001表示大寫(xiě)字母A,有時(shí)我們會(huì)“偷懶"的用65這個(gè)十進(jìn)制來(lái)表示A在ASCII中的編碼。8個(gè)比特位,可以沒(méi)有重復(fù)的最多表示2的8次方(255)個(gè)字符。
后來(lái),計(jì)算機(jī)得到普及,中文、日文、韓文等等國(guó)家的文字需要在計(jì)算機(jī)內(nèi)表示,ASCII的255位遠(yuǎn)遠(yuǎn)不夠,于是標(biāo)準(zhǔn)組織制定出了叫做UNICODE的萬(wàn)國(guó)碼,它規(guī)定任何一個(gè)字符(不管哪國(guó)的)至少以2個(gè)字節(jié)表示,可以更多。其中,英文字母就是用2個(gè)字節(jié),而漢字是3個(gè)字節(jié)。這個(gè)編碼雖然很好,滿足了所有人的要求,但是它不兼容ASCII,同時(shí)還占用較多的空間和內(nèi)存。因?yàn)椋谟?jì)算機(jī)世界更多的字符是英文字母,明明可以1個(gè)字節(jié)就能夠表示,非要用2個(gè)。
于是UTF-8編碼應(yīng)運(yùn)而生,它規(guī)定英文字母系列用1個(gè)字節(jié)表示,漢字用3個(gè)字節(jié)表示等等。因此,它兼容ASCII,可以解碼早期的文檔。UTF-8很快就得到了廣泛的應(yīng)用。
在編碼的發(fā)展歷程中,我國(guó)還創(chuàng)造了自己的編碼方式,例如GBK,GB2312,BIG5。他們只局限于在國(guó)內(nèi)使用,不被國(guó)外認(rèn)可。在GBK編碼中,中文漢字占2個(gè)字節(jié)。
2.2 bytes和str的異同
回到bytes和str的身上。bytes是一種比特流,它的存在形式是01010001110這種。我們無(wú)論是在寫(xiě)代碼,還是閱讀文章的過(guò)程中,肯定不會(huì)有人直接閱讀這種比特流,它必須有一個(gè)編碼方式,使得它變成有意義的比特流,而不是一堆晦澀難懂的01組合。因?yàn)榫幋a方式的不同,對(duì)這個(gè)比特流的解讀也會(huì)不同,對(duì)實(shí)際使用造成了很大的困擾。下面讓我們看看Python是如何處理這一系列編碼問(wèn)題的:
>>> s =
"
中文
"
>>>
s
'
中文
'
>>>
type(s)
<
class
'
str
'
>
>>> b = bytes(s, encoding=
'
utf-8
'
)
>>>
b
b
'
\xe4\xb8\xad\xe6\x96\x87
'
>>>
type(b)
<
class
'
bytes
'
>
從例子可以看出,s是個(gè)字符串類(lèi)型。Python有個(gè)內(nèi)置函數(shù)bytes()可以將字符串str類(lèi)型轉(zhuǎn)換成bytes類(lèi)型,b實(shí)際上是一串01的組合,但為了在ide環(huán)境中讓我們相對(duì)直觀的觀察,它被表現(xiàn)成了b'\xe4\xb8\xad\xe6\x96\x87'這種形式,開(kāi)頭的b表示這是一個(gè)bytes類(lèi)型。\xe4是十六進(jìn)制的表示方式,它占用1個(gè)字節(jié)的長(zhǎng)度,因此”中文“被編碼成utf-8后,我們可以數(shù)得出一共用了6個(gè)字節(jié),每個(gè)漢字占用3個(gè),這印證了上面的論述。在使用內(nèi)置函數(shù)bytes()的時(shí)候,必須明確encoding的參數(shù),不可省略。
我們都知道,字符串類(lèi)str里有一個(gè)encode()方法,它是從字符串向比特流的編碼過(guò)程。而bytes類(lèi)型恰好有個(gè)decode()方法,它是從比特流向字符串解碼的過(guò)程。除此之外,我們查看Python源碼會(huì)發(fā)現(xiàn)bytes和str擁有幾乎一模一樣的方法列表,最大的區(qū)別就是encode和decode。
從實(shí)質(zhì)上來(lái)說(shuō),字符串在磁盤(pán)上的保存形式也是01的組合,也需要編碼解碼。
如果,上面的闡述還不能讓你搞清楚兩者的區(qū)別,那么記住下面兩幾句話:
- 在將字符串存入磁盤(pán)和從磁盤(pán)讀取字符串的過(guò)程中,Python自動(dòng)地幫你完成了編碼和解碼的工作,你不需要關(guān)心它的過(guò)程。
- 使用bytes類(lèi)型,實(shí)質(zhì)上是告訴Python,不需要它幫你自動(dòng)地完成編碼和解碼的工作,而是用戶(hù)自己手動(dòng)進(jìn)行,并指定編碼格式。
- Python已經(jīng)嚴(yán)格區(qū)分了bytes和str兩種數(shù)據(jù)類(lèi)型,你不能在需要bytes類(lèi)型參數(shù)的時(shí)候使用str參數(shù),反之亦然。這點(diǎn)在讀寫(xiě)磁盤(pán)文件時(shí)容易碰到。
在bytes和str的互相轉(zhuǎn)換過(guò)程中,實(shí)際就是編碼解碼的過(guò)程,必須顯式地指定編碼格式。
1
#
!/usr/bin/env python3
2
#
-*-coding:utf-8-*-
3
4
"""
5
@author:fyh
6
@time:2019/5/31
7
"""
8
#
gbk編碼的bytes
9
b = bytes(
'
中國(guó)
'
, encoding=
'
gbk
'
)
10
print
(b)
#
b'\xd6\xd0\xb9\xfa'
11
print
(type(b))
#
12
13
str1 =
str(b)
14
print
(str1)
#
b'\xd6\xd0\xb9\xfa'
15
print
(type(str1))
#
16
17
#
指定編碼格式
18
str2 = str(b, encoding=
'
gbk
'
)
19
print
(str2)
#
中國(guó)
20
print
(type(str2))
#
21
22
#
再把字符串str2轉(zhuǎn)換為utf8編碼格式的bytes類(lèi)型:
23
b2 = bytes(str2, encoding=
'
utf8
'
)
24
print
(b2)
#
b'\xe4\xb8\xad\xe5\x9b\xbd'
25
print
(type(b2))
#
2.3 encode和decode?
上面說(shuō)過(guò)了,python3默認(rèn)的編碼時(shí)Unicode,用字符串表示,二進(jìn)制數(shù)據(jù)由bytes類(lèi)型表示。
- encode:將str轉(zhuǎn)換為bytes,是一個(gè)編碼的過(guò)程
- decode:將bytes轉(zhuǎn)換為str,是一個(gè)解碼的過(guò)程
1
#
!/usr/bin/env python3
2
#
-*-coding:utf-8-*-
3
4
"""
5
@author:fyh
6
@time:2019/5/31
7
"""
8
9
"""
10
其中decode()與encode()方法可以接受參數(shù), 其聲明分別為:
11
bytes.decode(encoding="utf-8", errors="strict")
12
str.encode(encoding="utf-8", errors="strict")
13
14
其中 encoding是指在解碼/編碼(動(dòng)詞)過(guò)程中使用的字符編碼(名詞)
15
16
errors是指錯(cuò)誤的處理方案,errrors參數(shù)默認(rèn)值是strict(嚴(yán)格的)意味著如果編解碼出錯(cuò)將會(huì)拋出UnicodeError
17
18
如果想忽略編解碼錯(cuò)誤 可以將errors設(shè)置為ignore
19
"""
20
21
22
#
編碼 encode
23
str1 =
"
中國(guó)
"
24
25
str1_utf8 = str1.encode(encoding=
'
utf8
'
)
26
print
(str1_utf8)
#
b'\xe4\xb8\xad\xe5\x9b\xbd'
27
print
(type(str1_utf8))
#
28
29
str1_gbk = str1.encode(encoding=
"
gbk
"
)
30
print
(str1_gbk)
#
b'\xd6\xd0\xb9\xfa'
31
print
(type(str1_gbk))
#
32
33
34
#
解碼 decode
35
str2 = str1_utf8.decode(encoding=
"
utf8
"
)
36
print
(str2)
#
中國(guó)
37
print
(type(str2))
#
38
39
str3 = str1_gbk.decode(encoding=
"
gbk
"
)
40
print
(str3)
#
中國(guó)
41
print
(type(str3))
#
ps:編碼和解碼時(shí),對(duì)應(yīng)的編碼方式要一致
ps:對(duì)數(shù)據(jù)的編碼解碼工作是通過(guò)返回值查看到最終結(jié)果的,前面的數(shù)據(jù)對(duì)象并不受影響
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

