提示:这里可以添加本文要记录的大概内容:
学习廖老师的struct、base64两篇文章产生的疑问及解决
提示:以下是本篇文章正文内容,下面案例可供参考
廖老师文里‘base64是把二进制数据转化为字符串的一种编码方式;struct是用来实现bytes和其他二进制转化的’。那python中这么多类型究竟是如何定义的?所谓的编码又是什么
《数据类型》
《编码》 这篇文章提到了ASCII编码、GB2312编码、Unicode编码、UTF-8编码。当然编码不止这些,还有例如汉明码、Base64编码等等。
本文重点区分ASCII、Unicode、UTF-8、Base64
关于编码更详细的,可阅读 《简析多种编码方式》
————————————————
计算机能处理的远不止数值,还可以处理文本、图形、音频、视频、网页等各种各样的数据,不同的数据,需要定义不同的数据类型。比如说3>2这个结果描述,我们用Bool类型的变量来描述很简洁。这也更符合了面向对象的特点了,对象不同,用的数据类型可能不同。
————————————————
参考文,写得挺好
涉及到计组的内容了。例如整型分为有符号整型、无符号整型,那么可以规定8bit的最高位是否代表符号。本质其实也是人为定义的规则去表示。
————————————————
《参考文》
首先计算机只认得二进制,0和1,所以我们现在看到的字都是经过二进制数据编码后的;计算机能针对0和1的组合做很多事情,这些规则都是人定义的;然后有了字节的概念,8比特一个字节,如01011100就是一个字节;
字符是用字节构成的,但多少字节,怎么构成我们认识的唯一的字符?这个由编码格式决定,也就是Unicode、GBK,(为啥要用字节?,因为历史觉得8比特很牛逼啊)。
字符串是字符的序列,各种计算机语言不同表示,如Redis就和C的字符串不一样,C是以 ‘\0’ 结尾;我们说的对字符的编码,而不是字符串;
**由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。**关于如何str–>bytes,可以见《 区分’ABC’和b’ABC’以及 str --> bytes》。
Python对bytes类型的数据用带b前缀的单引号或双引号表示。
————————————————
b’100’代表二进制100,对应十进制是4;
b’abc’,代表bytes类型,每个字符只占1个字符。
————————————————
《参考文1》
《参考文2》
'ABC’是str,b’ABC’虽然内容显示得和’ABC’一样,但bytes的每个字符都只占用一个字节。但’ABC’每个字符不一定占1个字节。
Python 3里面,str在内存里是unicode表示的,所以’中文’ == ‘\u4e2d\u6587’,类型都是str,属于应用层。
>>> ‘\u4e2d\u6587’
‘中文’
#1个汉字用unicode表示,是2个byte,这里\u4e2d是十六进制的写法。4e是0100 1110,2d是0010 1101,合起来16位2bytes。
>>> ‘中文’.encode(‘utf-8’)
b’\xe4\xb8\xad\xe6\x96\x87’
>>> ‘\u4e2d\u6587’.encode(‘utf-8’)
b’\xe4\xb8\xad\xe6\x96\x87’
#'\u4e2d’是unicode表示的字符,unicode只是表示它的图一个形式,但本质上被表示的对象还是字符,是str而不是bytes
由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。但如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。
以Unicode表示的str通过encode()方法可以编码为指定的bytes。一般可以编码成ascii或者utf-8。
>>> ‘ABC’.encode(‘ascii’)
b’ABC’
>>> ‘中文’.encode(‘utf-8’)
b’\xe4\xb8\xad\xe6\x96\x87’
>>> ‘中文’.encode(‘ascii’)
Traceback (most recent call last): File “stdin”, line 1, in module
UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position
0-1: ordinal not in range(128)
纯英文的str可以用ASCII编码为bytes,内容是一样的,含有中文的str可以用UTF-8编码为bytes。含有中文的str无法用ASCII编码,因为中文编码的范围超过了ASCII编码的范围,Python会报错。
在bytes中,无法显示为ASCII字符的字节,用\x##(##是8个二进制位的16进制)显示。所以上面代码中“中文”显示了b’\xe4\xb8\xad\xe6\x96\x87’ 。
b’i\xb7\x1d\xfb\xef\xff’ 占6个字节,i是一个字节,后面还有5个字节。因为i在ascii里,能够显示,但是后面的超出了ascii码的范围,因此才这样显示。
至于原因,我猜想:二进制文件通常不易于人看,因为人会看眼花,所以必须转为其他进制,16进制是最好的
反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法…(这个小板块几乎转载于廖老师,点击跳转)
————————————————
参考文
Python bytes 类型用来表示一个字节串。“字节串“不是编程术语,是我自己“捏造”的一个词,用来和字符串相呼应。
bytes 是 Python 3.x 新增的,在 Python 2.x 中是不存在的。bytes是一个类,表示“字节串”,它是在Python3中新增的,它不是一个基础类型
字节串(bytes)和字符串(string)的对比:
1、字符串由若干个字符组成,以字符为单位进行操作;字节串由若干个字节组成,以字节为单位进行操作。
2、字节串和字符串除了操作的数据单元不同之外,它们支持的所有方法都基本相同。
3、字节串和字符串都是不可变序列,不能随意增加和删除数据。
4、bytes 只负责以字节序列的形式(二进制形式)来存储数据,至于这些数据到底表示什么内容(字符串、数字、图片、音频等),完全由程序的解析方式决定。如果采用合适的字符编码方式(字符集),字节串可以恢复成字符串;反之亦然,字符串也可以转换成字节串。
说白了,bytes 只是简单地记录内存中的原始数据,至于如何使用这些数据,bytes 并不在意,你想怎么使用就怎么使用,bytes 并不约束你的行为。
5、bytes 类型的数据非常适合在互联网上传输,可以用于网络通信编程;bytes 也可以用来存储图片、音频、视频等二进制格式的文件。
6、字符串和 bytes 存在着千丝万缕的联系,我们可以通过字符串来创建 bytes 对象,或者说将字符串转换成 bytes 对象。
7、有以下三种方法可以达到这个目的:如果字符串的内容都是 ASCII 字符,那么直接在字符串前面添加b前缀就可以转换成 bytes。bytes 是一个类,调用它的构造方法,也就是 bytes(),可以将字符串按照指定的字符集转换成 bytes;如果不指定字符集,那么默认采用 UTF-8。字符串本身有一个 encode() 方法,该方法专门用来将字符串按照指定的字符集转换成对应的字节串;如果不指定字符集,那么默认采用 UTF-8。
【实例】使用不同方式创建 bytes 对象:
#通过构造函数创建空 bytes
b1 = bytes()
#通过空字符串创建空 bytes
b2 = b''
#通过b前缀将字符串转换成 bytes
b3 = b'http://www.baidu.com/python/'
print("b3: ", b3)
print(b3[3])
print(b3[7:22])
运行结果: b3: b’http://www.baidu.com/python/’ 112 b’c.www.baidu.com’
从运行结果可以发现,对于非 ASCII 字符,print 输出的是它的字符编码值(十六进制形式),而不是字符本身。非 ASCII 字符一般占用两个字节以上的内存,而 bytes 是按照单个字节来处理数据的,所以不能一次处理多个字节。
ASCII编码,将英文存储到计算机 GB2312编码和GBK编码,将中文存储到计算机 Unicode字符集,将全世界的文字存储到计算机
————————————————
《参考文章》
要在多语言环境中通用,那就是要使用UTF,这可以理解为存储数据格式。用了UTF是让大家都能识别数据,不然就会乱码;
Base-64的话,不是底层存储格式,只是为了数据交换用有,例如Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一。比如图片变成字符格式,这是一种应用格式。
————————————————
进制与数据类型的关系
”进制“是人为定义的关于数的规则而已。
python语言是电脑与人进行“交流”的语言,而电脑是2进制,为了方便人看懂,故设置不同进制。
————————————————
参考文章
计算机是由逻辑电路组成的,电路中通常只有两个状态,开关的接通和断开, 这两种状态正好可以用“1”和“0”表示。
————————————————
正常课本上:二进制(B)、八进制(O)、十进制(D)、十六进制(H);
python中:二进制(b)、八进制(o)、十进制(d)、十六进制(x);
需要注意:
1、区分b’100’ 与 b’ABC’ (不要觉得看到b就是二进制,进制仅仅针对于纯数字)
2、pyhon中关于十六进制有两种情况。0x61 与 ‘\x61’。答案在后面。
————————————————
通过人为去定义规则。计算了直接显示即可。
————————————————
这个问题来自于廖老师文章中的两句话
什么叫二进制数据、二进制数据类型?那势必还有八进制数据、十六进制数据等?bytes也是二进制数据类型吗?
从廖老师代码中可以发现,其实所有背后的本质都是二进制,因为计算机就是二进制。无非就是人为的去定义一些的规则而已,字节、字符、字符串,都是通过二进制由人为定制的规则而演变得到的。
但是计算机不能这样,因为这样就无法做到具体识别。
因此一般所谓的二进制数据类型仅仅只针对于 python基础类型 中的numbers的int(int即整型、即整数表示)。例如二进制整数常量、十进制整数常量。而不是什么二进制浮点型、二进制字符串型。
但需要注意的是,python3中又引入了一种新的“数据类型” – bytes,它也是属于二进制数据类型。
关于bytes为何要引入,只要记住一点:在网络上传输时必须要转换成bytes才能传输。否则一个字符具体对应几个字节会因为编码的不同导致而不同,这样传输就不统一。(这个是我盲猜的)
所以廖老师 《base64》 中的代码全是b’ ',就是因为base64目的就是为了能够让数据能在网络上进行传输;
所以上图2中 “好在Python提供了一个struct模块来解决bytes和其他二进制数据类型的转换。”就显而易见了。
————————————————
参考文,写得很好
需要尤其注意关于16进制表示:
1、python里的16进制是x,而课本上单讲进制不针对任何语言是H;
2、python里的16进制一定要区分 \x 、0x。具体见下区分
————————————————
\u : python3中,字符在内存里的表示是unicode。所以看到\u代表目前是unicode编码。
例如;‘中文’ == ‘\u4e2d\u6587’。一般unicode中一个中文字符对应两个字节,8位。这里为了人眼看,计算机一般显示16进制。
0x : 表示十六进制的int型变量。
例如0x61 表示int型的97
\x : 表示十六进制的字符型变量。
例如’\x61’ 表示str型,ASCII码为十进制97的字符,即’a’。换句话说 ‘\x61’ == chr(97)
————————————————
参考文,写得很好
不仅仅针对中文, 可以针对任何的字符串,代表是对字符串进行unicode编码。
一般英文字符在使用各种编码下, 基本都可以正常解析, 所以一般不带u;但是中文, 必须表明所需编码, 否则一旦编码转换就会出现乱码。 建议所有编码方式采用utf8。
在python3中,字符串默认创建即以Unicode编码存储,自然便可以存储中文。
例一:
u"我是含有中文字符组成的字符串。"
作用:后面字符串以 Unicode 格式 进行编码,一般用在中文字符串前面,防止因为源码储存格式问题,导致再次使用时出现乱码。
例子二:
string = ‘a’ 等效于 string = u’a’
Unicode中通常每个字符由2个字节表示。 u’a’ 即 u’\u0061’ 实际内存中为 [0000 0000] [0110 0001]
与普通字符相比,其他相对特殊的字符,其中可能包含转义字符,即那些反斜杠加上对应字母,表示对应的特殊含义的,比如最常见的”\n”表示换行,”\t”表示Tab等。
而如果是以r开头,那么说明后面的字符,都是普通的字符了,即如果是“\n”那么表示一个反斜杠字符,一个字母n,而不是表示换行了。
以r开头的字符,常用于正则表达式,对应着re模块。
例:r"\n\n\n\n” # 表示一个普通生字符串 \n\n\n\n,而不表示换行了。
作用:
去掉反斜杠的转移机制。(特殊字符:即那些,反斜杠加上对应字母,表示对应的特殊含义的,比如最常见的”\n”表示换行,”\t”表示Tab等。 )
应用:
常用于正则表达式,对应着re模块。所以廖老师中的《正则表达式》 中推荐在正则表达式前加一个r。
python3.x里,默认的str是(py2.x里的)unicode,bytes是(py2.x)的str,b”“前缀代表的就是bytes。
python2.x里,b前缀没什么具体意义, 只是为了兼容python3.x的这种写法。
例一:
response = b'Hello World!
' # b' ' 表示这是一个 bytes 对象
作用:b" "前缀表示:后面字符串是bytes 类型。
用处:网络编程中,服务器和浏览器只认bytes 类型数据。如:send 函数的参数和 recv 函数的返回值都是 bytes 类型。
例子二:
result = b'你好20190101'
字符串存储为Ascll码,无法存储中文。编译会报如下错误:
SyntaxError: bytes can only contain ASCII literal characters.
附:
在 Python3 中,bytes 和 str 的互相转换方式是
str.encode(‘utf-8’)
bytes.decode(‘utf-8’)
print(r’A\tA’) 结果为A\tA
print(b’A\tA’) 结果为b’A\tA’
print(u’A\tA’) 结果为A A
注意:b’A\tA’ 打印结果中自带一个b’',表示该字符串是一个字节数组
码字不易,三连,谢谢