Python 了解 bytes 与 str 的区别

news/2024/11/25 23:12:57/

Python 有两种类型可以表示字符序列

  • bytes:实例包含的是原始数据,即 8 位的无符号值(通常按照 ASCII 编码标准来显示)
  • str:实例包含的是 Unicode 码点(code point,也叫作代码点),这些码点与人类语言之中的文本字符相对应
a = b'h\x6511o'
print(list(a))
print(a)a = 'a\\u300 propos'
print(list(a))
print(a)# 输出结果
[104, 101, 49, 49, 111]
b'he11o'['a', '\\', 'u', '3', '0', '0', ' ', 'p', 'r', 'o', 'p', 'o', 's']
a\u300 propos

Unicode 数据和二进制数据转换

  • 把  Unicode 数据转换成二进制数据,必须调用 str 的 encode 方法(编码)
  • 把二进制数据转换成 Unicode 数据,必须调用 bytes 的 decode 方法(解码)
  • 调用这些方法时,可以明确指出字符集编码,也可以采用系统默认的方案,通常是 UTF-8

使用原始的 8 位值与 Unicode 字符串时需要注意的两个问题

该问题等价于:使用 bytes 和 str 时需要注意的两个问题

问题一:bytes 和 str 的实例互不兼容

使用 + 操作符

# bytes+bytes
print(b'a' + b'1')# str+str
print('b' + '2')# 输出结果
b'a1'
b2
  • bytes + bytes,str + str 都是允许的
  • 但 bytes + str 会报错
# bytes+str
print('c' + b'2')# 输出结果
print('c' + b'2')
TypeError: can only concatenate str (not "bytes") to str

同类型之间也可以用二元操作符来比较大小

assert b'c' > b'a'assert 'c' > 'a'

但 bytes 和 str 之间用二元操作符也会报错

assert b'c' > 'a'# 输出结果assert b'c' > 'a'
TypeError: '>' not supported between instances of 'bytes' and 'str'

判断 bytes 与 str 实例是否相等

两个类型的实例相比较总会为 False,即使字符完全相同

# 判断 str、bytes
print('a' == b'a')# 输出结果
False

格式化字符串中的 %s

两种类型的实例都可以出现在 % 操作符的右侧,用来替换左侧那个格式字符串(format string)里面的 %s

但是!如果格式字符串是 bytes 类型,那么不能用 str 实例来替换其中的 %s,因为 Python 不知道这个 str 应该按照什么字符集来编码

# %
print(b'red %s' % 'blue')# 输出结果print(b'red %s' % 'blue')
TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'str'

但是!反过来却可以,如果格式字符串是 str 类型,则可以用bytes 实例来替换其中的 %s,但结果可能不是预期结果

# % 
print('red %s' % b'blue')# 输出结果
red b'blue'
  • 这样会让系统在 bytes 实例上面调用 __repr__ 方法
  • 调用结果替换格式字符串里的 %s,因此程序会直接输出 b'blue',而不是输出 blue

问题二:操作文件句柄时需要使用 Unicode 字符串操作

不能使用原始的 bytes

向文件写入二进制数据会报错

# 写入二进制数据
with open('test.txt', "w+") as f:f.write(b"\xf1\xf2")# 输出结果f.write(b"\xf1\xf2")
TypeError: write() argument must be str, not bytes
  • 报错是因为 w 模式必须以文本模式写入
  • 将模式改成 wb 即可正常写入二进制数据
with open('test.txt', "wb") as f:f.write(b"\xf1\xf2")

读取文件中二进制数据

with open('test.txt', "r+") as f:f.read()# 输出结果(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 0: invalid continuation byte
  •  报错是因为 r 模式必须以文本模式读取
  • 以文本模式操纵文件句柄时,系统会采用默认的文本编码方案处理二进制数据
  • 所以,上面那种写法会让系统通过 bytes.decode 把这份数据解码成 str 字符串,再用 str.encode 把字符串编码成二进制值
  • 然而对于大多数系统来说,默认的文本编码方案是UTF-8,所以系统很可能会把 b'\xf1\xf2\xf3\xf4\xf5' 当成  UTF-8 格式的字符串去解码,于是就会出现上面那样的错误

将模式改成 rb 即可正常读取二进制数据

with open('test.txt', "rb") as f:print(b"\xf1\xf2" == f.read())# 输出结果
True

另一种改法,设置 encoding 参数指定字符串编码

with open('test.txt', "r", encoding="cp1252") as f:print(f.read())# 输出结果
ñò

python 编程icon-default.png?t=LA92https://edu.csdn.net/course/detail/36170


http://www.ppmy.cn/news/292708.html

相关文章

Linux下spi驱动分析与测试【详细流程】

驱动是基于ARM的pl022的SSP控制器,其支持三种通信格式:SPI、SSI以及Microwrite,llinux5.4内核下,SSP控制器驱动的路径为/drivers/spi/spi-pl022.c。下面将从spi-pl022.c文件开始分析SPI驱动。 1 AMBA总线 与platform总线相同&am…

YAMAHA 钢琴型号与年代对应表

YAMAHA不同时代对应的编号和主要型号 发行年 制造编号 主要系列型号 1946~ 40000 100 200 300 1954~ 50000 U1a U1b U1c U3a 1959~ 90000 100D u2a ucb u3b u3c u3D 1965~ 300000 U1E U2C U3E 1970~ 820000 U1F U2F U3F U5C U7B 1971~ 980000 U1G U2G U3G 1972~ 115…

Linux内核移植入门

文章目录 基本概念内核源码目录结构内核配置主目录Makefile各子目录Makefile如何配置内核?1. 配置仓库选取2.交叉编译器的修改3.体系结构体的选择4.修改配置文件 内核编译编译结果:几种linux内核文件的区别开发板上U-Boot启动linux内核内核Kconfig语法使用1.make menuconfig 是…

Linux内核开发人员考虑剔除对更多老旧平台的处理器支持

随着 Linux 5.10 走入长期支持(LTS),内核开发人员也对未来五年的平台支持展开了探讨,比如剔除干线内核项目中的大量旧款 CPU 的支持。 Phoronix 援引 Arnd Bergmann 的话称,包括 ARM 在内的缺乏生命迹象的老旧 CPU 架构…

联想U300 做的最漂亮的笔记本比苹果的Mac Air还漂亮的本

【曝光多图】联想U300 做的最漂亮的笔记本比苹果的Mac Air还漂亮的本 联想今年真的很给力啊~发布了彪悍的小Y的新一代,现在又推出UltraBook U300 U300S U400等等,网上已经是消息满天飞了,所以呢,我就来汇总一下,顺便抖…

U300 超高频读写器 - 固定式rfid读写器

超高频rfid读写器厂家专久智能提供的基于Impinj E710芯片制成的U300固定式rfid读写器,采用 Android 11 操作系统、四核 2.0GHz CPU,数据处理能力强大。 此款U300 超高频固定式读写器支持6dBic,9dBic 等多种天线,最大群读速率可达 …

四种经典的知识变现盈利模式,看你适合哪一种

哈喽,大家好,我是海哥,知识付费变现创业教练,教育公司培训总监,从事知识付费变现咨询10年,已助力3000人实现知识付费变现。 知识变现有四种典型的盈利模式,看看你合适哪一种? 模式1&…

Unity如何设计一个战斗系统

战斗系统的基本原理 在游戏中,战斗系统的基本原理是通过计算双方的属性和技能等信息,来模拟双方的战斗过程。在战斗过程中,玩家需要根据自己的策略和技能来进行操作,以便战胜对手。在战斗过程中,需要考虑到双方的攻击…