全网最适合入门的面向对象编程教程:55 Python字符串与序列化-字节序列类型和可变字节字符串

news/2024/12/22 9:50:51/文章来源:https://www.cnblogs.com/FreakEmbedded/p/18445350

全网最适合入门的面向对象编程教程:55 Python 字符串与序列化-字节序列类型和可变字节字符串

image

摘要:

在 Python 中,字符编码是将字符映射为字节的过程,而字节序列(bytes)则是存储这些字节的实际数据结构,字节序列和可变字节字符串的主要区别在于其可变性和用途,bytearray 是可变的字节序列,允许修改其内容。

原文链接:

FreakStudio的博客

往期推荐:

学嵌入式的你,还不会面向对象??!

全网最适合入门的面向对象编程教程:00 面向对象设计方法导论

全网最适合入门的面向对象编程教程:01 面向对象编程的基本概念

全网最适合入门的面向对象编程教程:02 类和对象的 Python 实现-使用 Python 创建类

全网最适合入门的面向对象编程教程:03 类和对象的 Python 实现-为自定义类添加属性

全网最适合入门的面向对象编程教程:04 类和对象的Python实现-为自定义类添加方法

全网最适合入门的面向对象编程教程:05 类和对象的Python实现-PyCharm代码标签

全网最适合入门的面向对象编程教程:06 类和对象的Python实现-自定义类的数据封装

全网最适合入门的面向对象编程教程:07 类和对象的Python实现-类型注解

全网最适合入门的面向对象编程教程:08 类和对象的Python实现-@property装饰器

全网最适合入门的面向对象编程教程:09 类和对象的Python实现-类之间的关系

全网最适合入门的面向对象编程教程:10 类和对象的Python实现-类的继承和里氏替换原则

全网最适合入门的面向对象编程教程:11 类和对象的Python实现-子类调用父类方法

全网最适合入门的面向对象编程教程:12 类和对象的Python实现-Python使用logging模块输出程序运行日志

全网最适合入门的面向对象编程教程:13 类和对象的Python实现-可视化阅读代码神器Sourcetrail的安装使用

全网最适合入门的面向对象编程教程:全网最适合入门的面向对象编程教程:14 类和对象的Python实现-类的静态方法和类方法

全网最适合入门的面向对象编程教程:15 类和对象的 Python 实现-__slots__魔法方法

全网最适合入门的面向对象编程教程:16 类和对象的Python实现-多态、方法重写与开闭原则

全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与“file-like object“

全网最适合入门的面向对象编程教程:18 类和对象的Python实现-多重继承与PyQtGraph串口数据绘制曲线图

全网最适合入门的面向对象编程教程:19 类和对象的 Python 实现-使用 PyCharm 自动生成文件注释和函数注释

全网最适合入门的面向对象编程教程:20 类和对象的Python实现-组合关系的实现与CSV文件保存

全网最适合入门的面向对象编程教程:21 类和对象的Python实现-多文件的组织:模块module和包package

全网最适合入门的面向对象编程教程:22 类和对象的Python实现-异常和语法错误

全网最适合入门的面向对象编程教程:23 类和对象的Python实现-抛出异常

全网最适合入门的面向对象编程教程:24 类和对象的Python实现-异常的捕获与处理

全网最适合入门的面向对象编程教程:25 类和对象的Python实现-Python判断输入数据类型

全网最适合入门的面向对象编程教程:26 类和对象的Python实现-上下文管理器和with语句

全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现

全网最适合入门的面向对象编程教程:28 类和对象的Python实现-Python编程原则、哲学和规范大汇总

全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函数的使用

全网最适合入门的面向对象编程教程:30 Python的内置数据类型-object根类

全网最适合入门的面向对象编程教程:31 Python的内置数据类型-对象Object和类型Type

全网最适合入门的面向对象编程教程:32 Python的内置数据类型-类Class和实例Instance

全网最适合入门的面向对象编程教程:33 Python的内置数据类型-对象Object和类型Type的关系

全网最适合入门的面向对象编程教程:34 Python的内置数据类型-Python常用复合数据类型:元组和命名元组

全网最适合入门的面向对象编程教程:35 Python的内置数据类型-文档字符串和__doc__属性

全网最适合入门的面向对象编程教程:36 Python的内置数据类型-字典

全网最适合入门的面向对象编程教程:37 Python常用复合数据类型-列表和列表推导式

全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列

全网最适合入门的面向对象编程教程:39 Python常用复合数据类型-集合

全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用

全网最适合入门的面向对象编程教程:41 Python常用复合数据类型-队列(FIFO、LIFO、优先级队列、双端队列和环形队列)

全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型

全网最适合入门的面向对象编程教程:43 Python常用复合数据类型-扩展内置数据类型

全网最适合入门的面向对象编程教程:44 Python内置函数与魔法方法-重写内置类型的魔法方法

全网最适合入门的面向对象编程教程:45 Python实现常见数据结构-链表、树、哈希表、图和堆

全网最适合入门的面向对象编程教程:46 Python函数方法与接口-函数与事件驱动框架

全网最适合入门的面向对象编程教程:47 Python函数方法与接口-回调函数Callback

全网最适合入门的面向对象编程教程:48 Python函数方法与接口-位置参数、默认参数、可变参数和关键字参数

全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数

全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类

全网最适合入门的面向对象编程教程:51 Python函数方法与接口-使用Zope实现接口

全网最适合入门的面向对象编程教程:52 Python函数方法与接口-Protocol协议与接口

全网最适合入门的面向对象编程教程:53 Python字符串与序列化-字符串与字符编码

全网最适合入门的面向对象编程教程:54 Python字符串与序列化-字符串格式化与format方法

更多精彩内容可看:

给你的 Python 加加速:一文速通 Python 并行计算

一文搞懂 CM3 单片机调试原理

肝了半个月,嵌入式技术栈大汇总出炉

电子计算机类比赛的“武林秘籍”

一个MicroPython的开源项目集锦:awesome-micropython,包含各个方面的Micropython工具库

Avnet ZUBoard 1CG开发板—深度学习新选择

SenseCraft 部署模型到Grove Vision AI V2图像处理模块

文档和代码获取:

可访问如下链接进行对文档下载:

https://github.com/leezisheng/Doc

image

本文档主要介绍如何使用 Python 进行面向对象编程,需要读者对 Python 语法和单片机开发具有基本了解。相比其他讲解 Python 面向对象编程的博客或书籍而言,本文档更加详细、侧重于嵌入式上位机应用,以上位机和下位机的常见串口数据收发、数据处理、动态图绘制等为应用实例,同时使用 Sourcetrail 代码软件对代码进行可视化阅读便于读者理解。

相关示例代码获取链接如下:https://github.com/leezisheng/Python-OOP-Demo

正文

字符编码和字节序列 bytes

在计算机内存中,我们遵循标准化的编码原则,普遍采用 Unicode 编码体系。然而,当需要将数据持久化保存至硬盘或进行网络传输时,我们则将其转换为 UTF-8 编码。举例来说,当我们使用记事本进行文档编辑时,从文件中读取的 UTF-8 字符将被转换为 Unicode 字符以适应内存处理。编辑工作完成后,系统再将这些 Unicode 字符转换回 UTF-8 编码,以确保文件保存的准确性和兼容性。这一流程确保了数据在不同平台和系统间的顺畅交流,满足了现代计算环境中对于数据编码的多样化需求。

image

image

image

我们可以通过如下代码获取我们自己计算机默认的编码方式:

import sys
print(sys.getdefaultencoding())

我们来看一下运行结果,显示系统默认 UTF-8 编码:

image

Python3 中明确区分字符串类型 (str) 和字节序列类型 (bytes),也称为字节流。内存,磁盘中均是以字节流的形式保存数据,它由一个一个的字节(byte,8bit)顺序构成。在前文中,我们提到字节是计算过程中最底层的存储格式,所以字符串实际上为内置的 bytes 类型。然而人们并不习惯直接使用字节,既读不懂,操作起来也很麻烦,人们容易看懂的是字符串。所以字符串和字节流需要进行转化,字节流转换为人们可以读懂的过程叫做解码,与此相反,将字符串转换为字节流的过程叫做编码。在下面的示例中,我们先声明了一个 bytes 数组,然后用 bytes 类的.decode 方法将其转换为我们可以看得懂的 Unicode 字符串。这个方法接受不同字符编码方式作为参数,示例代码如下:

_# 表示 Latin-1 编码中的 cliché_
_# b 表示在定义一个 bytes 对象_
_# \x 字符表示每个字节用十六进制数字表示_
bytestr = b'\x63\x6c\x69\x63\x68\xe9'
_# 输出这些字节的 ASCII 符号本身_
_# 对于 ASCII 来说是未知的字符还是保留原有的十六进制格式_
_# 输出结果包含了 b 字符,提示我们这是一个bytes,而不是字符串_
print(bytestr)
_# 用 Latin-1 编码来解码字符串,decode 方法返回一个正常字符串_
print(bytestr.decode("latin-1"))
_# 使用 iso8859-5 编码来解码字符串_
print(bytestr.decode("iso8859-5"))
_# 使用 CP437 编码来解码字符串_
print(bytestr.decode("CP437"))

运行结果如下:

image

我们也可以使用 encode 将字符串转换为 bytes 数组,示例代码如下:

str = "cliché"
_# 前 3 个编码为重音字符创建了不同的字节集合_
print(str.encode("UTF-8"))
print(str.encode("latin-1"))
print(str.encode("CP437"))
_# 第 4 个则无法处理这种情况 ,有未知字符_
print(str.encode("ascii"))

运行结果如下:

image

可以看到,最后一种情况抛出了异常,因为具有未知字符,有时候我们想要让那些未知字符以不同的方式进行处理。encode 方法还接受一个可选的字符串参数,名为 errors,用于定义这个字符应该如何处理。可选的值如下所示:

  • strict:strict 替换规则是默认的,当字节序列在我们所用的编码中无法表示某个字符时,会抛出异常;
  • replace:使用 replace 策略时,这个字符会用另外一个字符替换;
  • ignore:ignore 策略会直接省去不认识的字符;
  • xmlcharrefreplace:xmlcharrefreplace 策略创建一个 xml 实体表示 Unicode 字符,这样可以根据 XML 文档来转换字符串。

image

image

Python 有大约 100 种不同的编码格式,详情可以看如下链接:

https://docs.python.org/zh-cn/3/library/codecs.html#standard-encodings

一些编码格式有多个名称,比如'latin-1'、'iso_8859_1'和'8859’都是指同一种编码。在处理编码文件时,选择正确的编码至关重要。我强烈推荐使用 UTF-8 编码。UTF-8 不仅具备表示任何 Unicode 字符的能力,更在现代软件领域中已成为一种广泛接受的标准。

Python 源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为 UTF-8 编码。当 Python 解释器读取源代码时,为了让它按 UTF-8 编码读取,我们通常在文件开头写上这两行:

_#!/usr/bin/env python3_
_# -*- coding: utf-8 -*-_

第一行注释是为了告诉 Linux/OS X 系统,这是一个 Python 可执行程序,Windows 系统会忽略这个注释;

第二行注释是为了告诉 Python 解释器,按照 UTF-8 编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。

申明了 UTF-8 编码并不意味着你的.py 文件就是 UTF-8 编码的,必须并且要确保 IDE 正在使用 UTF-8 编码。以 PyCharm IDE 为例:

image

可变字节字符串 bytearray

bytes 类型与 str 类似,它们都是不可变的。这意味着一旦创建了一个 bytes 对象,我们就不能对其进行扩展或修改。尽管如此,我们仍然可以对 bytes 对象执行索引或切片操作,甚至搜索特定的字节序列。然而,在处理 I/O 操作时,这种不可变性可能会带来一些不便。因为在进行输入/输出操作时,我们经常需要缓存字节,直到它们准备好被发送。

例如,当从套接字接收数据时,可能需要多次调用 recv 函数才能接收完整的消息。在这种情况下,我们可以使用内置的 bytearray 类型来解决这个问题。bytearray 的行为类似于列表,但它包含的元素是字节。它的构造函数可以接受 bytes 对象作为参数进行初始化。此外,bytearray 还提供了 extend 方法,允许我们向数组中添加更多的 bytes 对象,例如在从套接字或其他 I/O 通道接收到更多数据时,这种灵活性使得 bytearray 在处理需要动态修改字节序列的场景中非常有用。

bytearray 用法如下:

Syntax: bytearray(source, encoding, errors)
Parameters:
-source[optional]: Initializes the array of bytes
-encoding[optional]: Encoding of the string
-errors[optional]: Takes action when encoding fails
Returns: 
Returns an array of bytes of the given size.

在下面的示例中,我们创建了两个 bytearray 数组,并使用 bytearray() 函数对字符串进行编码:

str = "Geeksforgeeks"_# encoding the string with unicode 8 and 16_
array1 = bytearray(str, 'utf-8')
array2 = bytearray(str, 'utf-16')print(array1)
print(array2)

代码输出如下:

image

我们也可以通过切片操作直接修改 bytearray:

array2[4:6] = b"\x15\xa3"
print(array2)

运行结果如下:

image

需要注意的是,如果我们想要操作 bytearray 中的单个元素,则需要传入一个 0~255 的整数值。这个整数代表的是一个特定的 bytes。如果我们用字符或 bytes 对象,将会抛出异常。

单字节字符可以通过 ord 函数(ordinal 的简写)转换成整数。这一函数返回表示一个单独字符的整数。示例代码如下:

b = bytearray(b'abcdef')
b[3] = ord(b'g')
b[4] = 68
print(b)

运行结果如下:

image

这里,我们在构造完成可变字节字符串后,将索引为 3 的字符(第 4 个字符,因为和列表一样,索引是从 0 开始的)替换为 103。它是通过 ord 函数返回的 ASCII 字符中的小写字母 g 所对应的数字。作为说明,我们也将下一个字符替换为字节数字 68,它对应 ASCII 字符中的大写字母 D。

bytearray 类型的一些方法让它可以像列表一样操作,我们也可以对其进行遍历、求其长度、使用 count 和 find 等方法,就像是对 bytes 或 str 对象一样。不同之处在于 bytearray 是可变类型,它可以用于从特定输入源构建复杂序列。

_# 创建bytearray_
array = bytearray(b"acbcdc")
_# 遍历_
for value in array:print(value)
_# 对元素b'c'使用count方法_
print("Count of c is:", array.count(b"c"))
_# 对元素b'c'使用find方法_
print("Count of c is:", array.find(b"c"))
_# 对元素b'c'使用len方法_
print("Count of bytes:", len(array))

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/807224.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zookeeper 基础学习

Zookeeper 基础学习 ​ Zookeeper 官网: http://zookeeper.apache.org/ 注:以下操作在CentOS7环境操作。 ​ Zookeeper 是 Apache 的一个分布式服务框架,是 Apache Hadoop 的一个子项目。官方文档上这么解释 Zookeeper,它主要是用来解决分布式应用中经常遇到的…

妙用编辑器:把EverEdit变成计算器

妙用编辑器:把EverEdit变成计算器 应用场景 日常工作过程中,会存在需要计算一些数据的场景,调用系统的计算器当然可以完成这项工作,但是需要来回切换,且系统自带的计算器没有表达式计算功能,真是不方便。 解决办法 一般比较流行的文本编辑器都支持脚本语言,比如:EverEd…

轻松搞定Java毕设:为全国大学生提供高效、优质的Java毕业设计代做服务

随着毕业季的临近,许多大学生面临着毕业设计的巨大压力。尤其是对于那些选择计算机相关专业的学生来说,毕业设计通常要求在一个较短的时间内完成复杂的项目开发,这对于技术掌握尚不成熟的学生来说无疑是一个巨大的挑战。再加上其他课程的压力和生活的琐事,毕业设计可能会成…

JAVA毕设代做(项目+论文+源码)

马上就要做毕业设计啦,计算机专业的小伙伴们终于开始紧张啦~ 但是Java相关的毕业设计,真的太难啦,都不知道做什么选题!!! 如果你平时没认真学,那么很可能根本就不知道怎么做毕业设计! 尤其是对于摸鱼上瘾的同学,稍不注意就容易挂掉! 大家现在担心的无非下面几点! 我…

星座图整形技术在光纤通信中的matlab性能仿真,分别对比标准QAM,概率整形QAM以及几何整形QAM

1.算法仿真效果 matlab2022a仿真结果如下(完整代码运行后无水印):2.算法涉及理论知识概要星座图整形技术(Constellation Shaping Techniques)是现代光纤通信系统中提升数据传输效率的关键技术之一,通过优化星座点的布局和调制符号的使用概率,能在不增加系统功率或带宽的…

用难测的期待去对抗既定的焦虑和迷茫

大三到今天,经历了很多,不管是两次开发实习,还是一边秋招一边考公,或是毕业一个月后被鸽转正,又或是无数次的面试和考试,无数次的高铁和大巴,无数次的破而后立......都让我改变了此前狭隘的看法。回顾以往,其实我从很早以前就觉得路好像是直来直去的,一眼能看到底部,…

基于无线传感器网络的节点分簇算法matlab仿真

1.程序功能描述 对传感器网络进行分簇,在分簇过程中考量的有节点能量状态、节点拓扑位置、孤立节点删除等条件。与LEACH算法比较,对比如下几个方面指标: 1.网络从初始状态直到首个节点因能量耗尽而死亡的持续时间。 2.显示了随着时间的变化,一些节点开始死亡,整个网…

《Java 高级篇》八:新特性

Java 中的一些新特性:Lambda 表达式、函数式接口、Stream API。Author: ACatSmiling Since: 2024-10-01Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一…

高级语言程序设计第二次作业

这个作业属于哪个课程 2024高级语言程序设计 (福州大学 - 计算机与大数据学院)这个作业要求在哪里 高级语言程序设计课程第二次个人作业学号 052205124姓名 林宇作业内容: 1.编写并运行书本第3章3.11 编程练习题目中的第1题~第8题 (1):通过试验(即编写带有此类问题的程序)…

《Java 高级篇》六:I/O 流

Java 中的文件系统和 I/O 流。Author: ACatSmiling Since: 2024-10-01字符编码 字符集 Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。编码表的由来:计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,…

《Java 高级篇》七:线程和线程池

Java 中线程的创建方式,以及线程池的应用。Author: ACatSmiling Since: 2024-10-01程序、进程和线程 程序(program):是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 进程(process):是程序的一次执行过程,或是正在运行的一个程序。…

《Java 高级篇》五:数据结构

Java 中的数组和集合,ArrayList、HashMap 的源码和底层数据结构分析。Author: ACatSmiling Since: 2024-10-01概述 在 Java 语言中,数组(Array)和集合都是对多个数据进行存储操作的结构,简称Java 容器。此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储。 数组…