oeasy教您玩轉python - 008 - # ascii碼表
ASCII 碼表
回憶上次內容
通過 help()可以從 python 命令行模式進入到幫助模式
通過 q 退出
ord(c)和 chr(i)
ord
通過字符找到對應的數(shù)字chr
通過數(shù)字找到對應的字符這是倆函數(shù)
這倆是一對,相反相成的
字符
的本質是數(shù)字
Python 里面的字符對應著一些數(shù)字
a
對應 97b
對應 98c
對應 99可是,為什么是這樣的對應關系,誰規(guī)定的,必須的么???
小寫字母
#輸出a,b,c
ord("a")
ord("b")
ord("c")
#輸出z-a的數(shù)字差距,相對序號
ord("z")-ord("a")
#輸出a的相對序號
ord("a")-ord("a")
a、b、c 這些字符是挨著的
正好從0到25,總共26個數(shù)字??
對應數(shù)字也是挨著的

編碼規(guī)律
從 a-z 應該都是挨著的
26 個英文字母之間,數(shù)值差距是 25,說明都是挨著的
為什么是從 97 開始?
應該還有別的字符
除了小寫字母之外、大寫字母、數(shù)字、符號他們都是如何的分布的呢?
我想把所有 ASCII 字符 0-127 全都打出來
可以么?
遍歷范圍

for i in range(0,128): ? ?
????????print(i,end=",")
我們先把0-127 挨牌兒捋一遍

然后如何找到數(shù)字對應的字符呢?
對應字符
通過數(shù)字找到對應的字符是chr

for i in range(0,128): ? ?
????print(hex(i),chr(i),sep=":",end=" ? ?")
print(hex(i),chr(i),sep=":",end=" ? ?")
結束時輸出3個空格
分隔符為冒號
輸出i的字符狀態(tài)
輸出i的十六進制狀態(tài)
hex(i)
chr(i)
sep=':'
end=" ? ?"
結果如何呢?
結果

這不是很整齊啊
為什么在 0xa-0xc 好像換行很突然
后面可以看到字符和序號一一對應的關系
不過不是很明確
有什么方式可以看起來更明確么?
安裝 ASCII
sudo apt install asciiDec 對應的是 10 進制數(shù)
Hex 對應的是 16 進制數(shù)
后面的是具體字符
字符包括
控制
符號
英文大小寫字母
這樣就把各種字符和一個二進制數(shù)字對應起來了

這個 ASCII 什么時候開始有的呢?
ASCII 碼表
1967 年的時候就有了最初這個 ASCII 碼表??
實際上計算機中所有的數(shù)據(jù)都是 0 和 1
當時計算機用高電平和低電平分別表示 0 和 1
這建立起了
字符
和二進制數(shù)
的映射關系
字符
和二進制數(shù)
的映射關系
如果不一致面對同一個二進制數(shù) 01010101
就會映射到不同的字符
人們看到不同的字符就認為是亂碼
當時美國的工程師定義了一套編碼規(guī)則
A
mericanS
tandardC
ode forI
nformationI
nterchangeASCII
美國信息交換標準代碼

由來
這標準是美國信息交換標準代碼是由美國國家標準學會制定的
(American National Standard Institute , ANSI )
最初是美國標準
后來是國際標準化組織定為國際標準
(International Organization for Standardization, ISO)
稱為 ISO 646 標準
最后一次更新則是在 1986 年
到目前為止共定義了 128 個字符
解碼 ASCII

我們找到小寫的
a
這是他的
4321
位第四位
這是他的
765
位高三位
先向上找到
110
再向左找到
0001
在前面加一個
0
得到(
01100001
)2進制
對應著(
97
)10進制數(shù)
也就是(
0x61
)16進制數(shù)
剛好對應一個字節(jié)
對應關系
1 個 字節(jié) byte
正好 8 個 bit 位
相當于 2 位 16 進制數(shù)
16 進制數(shù) 更容易讀出
十六進制數(shù)很適合輸出字節(jié)狀態(tài)
聽起來找到了字符和字節(jié)狀態(tài)之間的映射對應關系
我們能在游樂場上驗證一下嗎?
游樂場
進入 python3 幫助模式
我們可以查詢 hex
hex 對應 hexadicimal 十六進制
help(hex)

動手
#得到a的序號
ord("a")
#輸出97對應的16進制形式
hex(97)
#找到a對應的16進制形式數(shù)字對應的字符
????hex(ord("a"))
0x61
就是十六進制的61
0x
是十六進制的前綴標志

可是為什么 16 進制使用
0x
作為前綴?
0x 前綴
x 的起源
0x 的 x 是取自 hex 的 x

0 的起源
C 語言繼承了類似設定
0 開頭表示數(shù)字
0x 開頭表示 16 進制數(shù)
變量名開頭不許是數(shù)字
0 開頭肯定是數(shù)字
但正常情況下寫數(shù)字不會用 0 開頭
這保證 0 開頭很容易和 10 進制區(qū)分開
在 C 語言之前的 B 語言用 0 開頭表示 8 進制
python 也繼續(xù)繼承
編碼 encode
解碼 decode
字符對應著數(shù)字
數(shù)字也可以轉化為字符
字符和二進制數(shù)之間的關系其實是
編碼解碼
編碼
就是用預先規(guī)定的方法將文字、數(shù)字、其它對象編成數(shù)碼
將信息、數(shù)據(jù)轉換成規(guī)定的電脈沖信號
簡單來說就是給大白菜編個號

解碼是編碼的逆過程
用特定方法,把數(shù)碼還原成它所代表的內容
將電脈沖信號、光信號、無線電波等轉換成它所代表的信息、數(shù)據(jù)等的過程
簡單說就是掃條碼知道這個是一個大白菜并知道價格等

我們用python試試編碼解碼
encode和decode

str(字符串)
'a'
encode(編碼)之后 為 bytes(字節(jié)序列)b'\x61'

bytes(字節(jié)序列)
b'\x61'
decode(解碼)之后為 為 str(字符串)'a'
編碼(encode) 和解碼(decode) 互為逆運算
很像
字符(chr)和 序號(ord)
編碼解碼
可以先編碼再解碼
也可以先解碼再編碼
繞來繞去
也沒做神馬??

掌握這個基礎是最起碼
基本功要練得硬橋硬馬
實戰(zhàn)方能穩(wěn)扎穩(wěn)打
否則以后各種亂碼

字節(jié)除了用十六進制顯示之外
還可以用二進制顯示么?
bin(number)
這次我們來試試把數(shù)字轉化為二進制形式
查詢 bin
bin 對應 binary 二進制


動手
#得到a的序號ord("a")#輸出97對應的16進制形式bin(97)#找到a對應的十六進制形式bin(ord("a"))0b1100001
是二進制數(shù)1100001
0b
是 2 進制數(shù)的前綴標志正如
0x
是 16 進制數(shù)的前綴標志

和 ASCII 表對比
驗證成功
這充分證明了我們用的確實是 ASCII 表?。?!????
廢話!??
我們會用 hex、bin 把 10 進制數(shù)轉化為八進制、二進制形式
能把其他進制轉化回十進制么?
其他進制 轉化為回 10進制 int(number)
用的是 int
這個 int 什么來歷?
我們 help()里面去找找
大小字母差值
0x41-0x5A
這個范圍是大寫字母0x61-0x7A
這個范圍是小寫字母
#輸出a的ASCII碼
ord("a")#輸出A的ASCII碼
ord("A")
#輸出大小寫之差
ord("a")-ord("A")
#差值的16進制形式
hex(ord("a")-ord("A"))
#差值的2進制形式
bin(ord("a")-ord("A"))
大寫字母和小寫字母相差(
32
)10進制
正好是(
0x20
)16進制
為什么不多不少
就差 0x20 呢?
怎么那么寸呢???
ASCII 碼表趣事
其實最初不是相差 0x20
這個 0x20 正好是一個二進制位
對應 b6 這個位
之前 ibm 的 EBCDIC 編碼并不是這樣的
那為什么要改成這樣子呢?
有了這種對應關系之后
修改1位之后,都變成小寫字母
然后直接查找就好了
The X3.2.4 task group voted its approval for the change to ASCII at its May 1963 meeting.
Locating the lowercase letters in columns 6 and 7 caused the characters to differ in bit pattern from the upper case by a single bit, which simplified case-insensitive character matching and the construction of keyboards and printers.
做大小寫不敏感的字符串查找就快多了
這個 0x20 發(fā)生在 1963 年 5 月
ASCII 碼表范圍
0x41-0x5A
這個范圍是大寫字母0x61-0x7A
這個范圍是小寫字母0x30-0x39
這個范圍是數(shù)字數(shù)字的編碼減去
0x30
正好得到數(shù)字本身
我們再來看看 ASCII
ASCII
0x20-0x7F
之間有各種符號0x00-0x1F
之間的東西是什么?目前還不知道
也許有一天可以進行進一步地探索
可以肯定都是
很多字符來自與更早之前的摩斯電碼
更早之前的摩斯電碼
ASCII 也不是從無到有的
在 ASCII 之前就有摩斯電碼
也是一種編碼方法
《oeasy 教您玩轉電路基礎》第 18 話介紹過
下圖是他的編碼表
分成長和短兩種信號,就是嘀和嗒
摩斯電碼通信規(guī)則
下圖是他的通信規(guī)則
三個斷確認本字符結束了
三個斷也就是字符之間的分隔符
錄入狀態(tài)并不是 0、1 兩種狀態(tài)
而是長、短、暫停三種狀態(tài)
為什么這樣編碼呢?
效率問題
編碼的規(guī)則是常用的字符點擊次數(shù)少
T
、E
出現(xiàn)頻率最高所以用一次點擊電鍵的數(shù)量
按照字符出現(xiàn)概率分配對應點擊數(shù)量
本質上是一棵霍夫曼樹
當時完全由人進行發(fā)射和接收
每個人發(fā)送數(shù)據(jù)的速度是不固定的
每個人接收數(shù)據(jù)的速度取決于發(fā)送人的發(fā)送速度
現(xiàn)查表是來不及的
需要熟悉編碼表和常用縮寫
這就是早期使用電來進行編碼的過程
我們現(xiàn)在回到 ASCII 碼
最后我們來總結一下
總結
數(shù)制可以轉化
bin(n)可以把數(shù)字轉化為
2進制
hex(n)可以把數(shù)字轉化為
16進制
int(n)可以把數(shù)字轉化為
10進制
編碼和解碼可以轉化
encode 編碼
decode 解碼
ASCII 碼表范圍
數(shù)字的編碼減去
0x30
正好得到數(shù)字本身0x41-0x5A
這個范圍是大
寫字母0x61-0x7A
這個范圍是小
寫字母0x30-0x39
這個范圍是數(shù)字
0x20-0x7F
之間有各種符號0x00-0x1F
之間的東西是什么???我們下次再說