python数据类型——bytes和bytearray
bytes 和 bytearray
bytes 和 bytearray 都是⼆进制世界的成员,⽤⼆进制的⽅式去理解才能看清他的本质。
理解bytes 和 bytearray
0 和 1 是计算机⼯作的根本,单个的0和1只能表达两种状态,⽆法满⾜我们复杂的计算,于是计算机使⽤了8位即⼀个byte作为⼀个储存的基本单位。byte 由 8bit 组成,例如00000001,也可以表⽰为16进制的形式:0x01, 0x为固定前缀,表⽰该数使⽤16进制表⽰⽅式,此外0o前缀为8进制,0b 为⼆进制形式,以此区分。bytes 从字⾯上理解是byte 的复数,也就是多个byte组成的序列。这⼀点与字符串与字符的关系类似。
于是,我们可以这样理解,字符串是由⼀个个字符顺序储存组成的序列,其中每个元素为⼀个字符。bytes 是由⼀个个byte组成的序列,每⼀个元素是⼀个byte。
bytearray是⼀个由byte为元素组成的array,其中每⼀个元素为⼀个byte。在python官⽅⽂档中,作者简单的定义了这两个类型。翻译为
bytes:可以看作是⼀组⼆进制数值(0-255) 的 str 序列
bytearray :可以看作是⼀组⼆进制数值(0-255) 的 list 序列
python中值的表⽰
在计算机中表⽰数有多种表⽰⽅式,普通的表⽰⽅式就是10进制的数值表⽰⽅法,例如a=10,此外还有8进制,16进制,2进制的表⽰⽅式,分别使⽤前缀0o和0x和0b表⽰。
a = 97
a = 0b01100001
a = 0x61
a = 0o301
使⽤上⾯4种⽅式定义的值均为⼗进制数97,也就是上⾯四种⽅式是等价得,只是使⽤不同的进制表⽰同⼀个值。
除了使⽤数值可以有不同的表⽰⽅式外,还可以使⽤字节的⽅式来定义⼀个值,⽽字节该如何书写?python使⽤了⼀个特殊字符串来表⽰字节,这个特殊字符可以使⽤前缀\x,\o, \b和\ 表⽰,分别表⽰16,8,2,10进制的表⽰⽅式,特殊字符后是对应的进制表⽰值。⽰例
a = "a"
a = "\b01100001"
a = "\x61"
a = "\o301"
同样得,这样得四种⽅式是等价得,a变量的值均为"a"。以上是单字节的字符的表⽰,多字节字符或者是⼀个字符串同样可以如此定义。
# 使⽤encode查看⼀下中国的⼆进制编码为
# 因此,我们可以使⽤这个字节表⽰来定义“中国”
a = '\xe4b8ade59bbd'# 或者 '\xe4\xb8\xad\xe5\x9b\xbd',两种⽅式均可
# 其8进制可以如此计算
num = int.from_bytes(a, "big") # 将这段字符串转化为内存等值的数值
print(oct(num)) # 打印该数值的8进制表⽰,结果为字符串类型。在该字符串加上\o前缀即可
# 最后打印结果
print(a) # ==> "中国"
# 再假如我们需要定义⼀个字符串abc,可以使⽤下⾯的⽅式
a = "abc"
a = "\x616263"# 由于abc的ascii码分别为 0x61 62 63
a = "\o301302303"# 由于abc的ascii码分别为 0o301 302 303
a = "\979899"# 由于abc的ascii码分别为 979899
进制转换
字节,数值,字符等类型可以使⽤下⾯的⽅式进⾏转化。还包括值得不同进制表⽰,字符串得不同进制表⽰,⽰例:
# 内置函数
chr(97) # ==> "a"
ord("a") # ==> 97
# 将⼀个10进制数,转化为其他进制的数的字符串表⽰得内置函数,注意,结果都是字符串,⽽不是对应进制的数值
bin(97) # ==> '0x61'
oct(97) # 8进制字符 '0o301'
hex(97) # 2进制字符 '0b01100001'
# 也可使⽤format完成
字符串长度和字节#带前缀 0x
format(97,"#x") # ==> '0x61'
format(97,"#o") # 8进制字符 '0o301'
format(97,"#b") # 2进制字符 '0b01100001'
#不带前缀
format(97,"X") # ==> '61'
format(97,"o") # ==> '301'
format(97,"b") # ==> '01100001'
# 3.6+版本使⽤⽅法
# f'{255:X}' 和 f'{255:#X}' ===> " FF " 和 "0xFF"
# 使⽤c 风格得表⽰
"%x"%10 # ==> 'a'
"%o"%10 # ==> '12'
# 带前缀
"%#x"%10 # ==> '0xa'
"%#o"%10 # ==> '0o12'
将⼀个字节或者字符或者字符串转化为值类型可以使⽤如下的⽅式。
ord("a") # ==> 97
int.from_bytes(b"a", "big") # 97 类型为int,指定⼤端模式(⼩地址存多字节⾼位)
# 以下两种形式等价
int.from_bytes(b"abc", "big") # ==> 得到三字节长度的数值
int.from_bytes(bytes("abc"), "big") #
bytes类型
将⼀个str 转化为 bytes 的本质是将str中的每个字符转化为该字符的⼆进制编码形式。例如 a 的⼆进制为 0x65。
# 将字符串abc 中每⼀个字符转化为⼆进制编码形式就是bytes类型
s = "abc"
bs1 = bytes("abc") # bytes()第⼀个参数为⼀个可迭代对象,将每⼀个元素转为⼆进制的表⽰⽅式
print(s) # 'abc'
print(bs1) # b'abc' python检测到这个⼆进制序列可以使⽤字符abc表⽰,但是为了区别于abc的字符串,所以使⽤ b'abc',只是给⼈看的⼀种表⽰结果。实际的值应该是⼀个个字节。# 我们看⼀下单个元素
print(s[0]) # 'a'
print(bs1[0]) # 97 ⽽不是 b'a',对于单个字节0x61, python使⽤了⼗进制数97表⽰
⼆进制类型bytes使⽤b'abc'的表⽰⽅式,只是尝试将这个序列中的元素翻译为⼈类可以看懂的形式,实际在变量内存中储存的为⼀个个⼆进制字节0x61 0x62 0x63,这样的三个字节可以根据数据类型的不同翻译成不同的结果。
b2 = bytes( [97,98,99] )
print(b2) # ==> b'abc'
这就对上⾯结论最佳证明,出现该结果的原因是,python中的列表 [97, 98, 99] 在内存中⼆进制储存和字符串abc储存的值是相同的,所以使⽤python来展⽰这段内存时,它使⽤b'abc'的⽅式进⾏展⽰。
bytes类型转化
字符串转bytes类型
# 将返回 bytes 类型 b" abc ",可以添加encoding参数指定字符串的编码⽅式
bs1 = bytes("abc","utf-8")
# 可以使⽤字符的16进制字符表达形式
bs2 = bytes('\x61\x62\x63',"utf-8")
# 直接对字符进⾏编码成⼆进制形式
bs2 = "abc".encode()
# 16进制字符转为bytes类型
b1 = bytes.fromhex("61 62 63") # ==> b"abc" "61,62"是两个16进制数组合,单个值不能超过 7F也就是不能超过127 ,否则⽆法对应ASCII表中的字符
b1.hex() # ===> '616263' ASCII码中abc字符对应的16进制数组成的字符串,上⾯函数的逆运算。
数值转化为bytes类型
想要使⽤数值来定义⼀个不能直接使⽤ bytes(97) 的⽅式来定义,这不会在内存中储存⼀个⼆进制的 97,⽽是会开辟97个字节,每个字节的值为0x00。这是需要注意的⼀点,如果想要储存⼀个97,可以使⽤列表来实现。
# 传⼊数值类型可迭代对象
b1 = bytes(range(97,100)) # ==> b'abc'
b2 = bytes([97,98,99]) # ==> b'abc'
b3 = bytes([97]) # ==> b'a'
# 直接传⼊10进制数值对象⽽不是可迭代对象,将会⽣成对应数值字节的空bytes
b4 = bytes(3) # b'\x00\x00\x00' 三个空字符的 bytes
# 通过数值转化将8进制,16进制数字⽣成bytes对象
b5 = bytes([int("61",16)]) #16进制61 == > 10 进制 ==> bytes ==> b"a" (使⽤字符a表⽰)
b6 = bytes([int("61", 8)]) # 8进制61 == > 10 进制 ==> bytes ==> b"1" (使⽤字符1表⽰)
# 也可利⽤bytes 对象转化为 10 进制数值
num = int.from_bytes(b"abc","big") # "abc"对应的三个字节拼接在⼀起作为⼀个⼆进制数,并计算为10进制数输出
print(num) # ===> 6382179
以上是将数值和字符串转化为字节类型,这是常⽤的类型转化⽅式,同样的,也可以将字节转化为字符或者值的类型。使⽤以下的⽅法即可
bytes转数值
bytes类型转化为值类型使⽤数值使⽤ int的⼀个类⽅法from_bytes即可,⽰例:
num = int.from_bytes(b“abc”, "big") # 将这个bytes对象转化为内存等值的数值
bytes的⽅法
bytes对象的⽅法和字符串的⽅法基本⼀致,可以进⾏字符串的⼏乎所有操作,例如字符串的replace,split,partation等操作,唯⼀需要区别的是。字符串的操作操作的对象是⼀个字符串或者单个字符,⽽bytes对象操作的是⼀个bytes⼆进制字节,例如进⾏字符串替换时:
"abc".replace("a", "x") # 将字符a 替换为 x
# ⽽在bytes对象
b"abc".replace(b"a", b"x") # ⽆论是参数中的对象还是对象本⾝都是bytes类型,有b“”前缀标识
其他⽅法类⽐于str的⽅法,并结合官⽅⽂档即可。
bytearray
bytearray类似于中的list数据类型,bytearray中的每⼀个元素始终为⼀个字节值,也就是 0x00 - 0xff 区间的⼀个值,如果不在该范围内的值,在指定了编码⽅式的情况下可以按照字节遍历。
# 初始化⼀个bytearray对象。同样需要⼀个可迭代对象作为参数,将会按照字节遍历整个可迭代对象,有以下的⽅式
bytearray("abc", encoding="utf-8") # abc字符串使⽤utf-8的⽅式编码为字节,每个字节作为bytearray对象的⼀个元素储存即可。
bytearray(b"abc") # 也可以使⽤bytes 类型,⽽使⽤bytes类型就没有编码⼀说了
bytearray([97, 98, 99]) # 使⽤可迭代对象,内部元素为⼀个⼀个0-255的数值类型。
ba1 = bytearray(range(97,103)) # 可迭代当然包括range对象
ba1 # bytearay对象,==> bytearray(b"abcdef")
ba1[0] # ==> 97 (integer)
ba1[1:4] # 切⽚ ==> bytearray(b'bcd')
# 赋值,可变 bytearray
ba[ 4 ] = 122 # 122整型对应字符"z", ==> b"e" --> b"z"
ba # bytearray(b"abcdzf" )
ba1[1:4] = b"xyz"# 切⽚赋值,替换ba1[1:4]的内容, 只有bytes 或bytearray 序列可赋值
bytes和bytearray类型之间可以直接进⾏转化,bytes()中可以传⼊⼀个bytearray对象作为参数,并且不存在编码问题,因为两个类型都是⼀个⼆进制的序列。
python在展⽰bytearray对象,使⽤的是bytesarray(b"abc") 的⽅式,其实,不妨理解为 bytearray( [ b"a", b"b", b"c" ] ) 的形式。也就是每个元素为字节列表。所以byteaarray实现了和列表对象的⽅法,并且可以进⾏元素的替换,也就是与列表相同,他是⼀个可变类型的对象。⽽bytes 与字符串都是不可变的,⽆法对单个元素进⾏替换,对象⼀旦产⽣将不可变。如果需要改变,需要新建⼀个新的对象。
bytearray的⽅法
类似与列表对象,可以进⾏切⽚,append, extend,insert等操作,同样的,由于内部的元素都是⼀个个字节对象,对单个元素操作时只能操作单字节的对象,⽽执⾏extend这类处理可迭代对象⽅法,也要求可迭代对象内部的所有元素为单字节对象。单字节对象,可以是 b"a"类似的单字节对象或 0-255的数值。因为⼀个字节只能储存256中状态。以下是⼏个简单的⽰例
a = bytearray(b"abc")
a.append(100)
print(a) # bytearray(b"abcd")
a.append(b"e")
print(a) # bytearray(b"abcde")
print(a) # bytearray(b"abcdeabcde")
a.insert(0, b"A")
print(a) # bytearray(b"Aabcdeabcde")
bytes(a) # b"Aabcdeabcde"
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论