[Python学习日记-30] Python中数据类型与文件操作的补充(Bytes 类型、字符编码的转换、深浅 Copy)

news2024/9/28 9:52:46

[Python学习日记-30] Python中数据类型与文件操作的补充

Bytes 类型

字符编码的转换

深浅 Copy

Bytes 类型

一、定义

        Bytes 类型是指一堆字节的集合,在 Python 中以 b 开头的字符串都是 Bytes 类型。从前面学习的字符编码当中知道,数据存到硬盘当中都是只能存储二进制的,而且数据往硬盘上存就要以相应的字符编码(ASSCII、GBK、UTF-8)来转成二进制后在存储

文字 ——> utf-8/gbk ——> 二进制
图片 ——> jpg/png ——> 二进制
音乐 ——> mp3/wav ——> 二进制
视频 ——> mp4/mov ——> 二进制

        Bytes类型是以十六进制的形式表示两个十六进制数构成一个 Byte,并且以 b'' 来标识的字节串,如下所示

b'\xe4\xb8\x96\xe7\x95\x8c\xe5\x92\x8c\xe5\xb9\xb3'

二、作用

        计算机只能存储和读取二进制, 所以我们的字符、图片、视频、音乐等想存到硬盘上,也必须以正确的方式编码成二进制后再进行存储。

  • 对于文字,我们可以以 GBK 编码,也可以以 UTF-8、ASCII 编码
  • 对于图片,必须编码成 PNG、JPEG 等格式
  • 对于音乐,必须编码成 MP3、WAV 等

        在 Python 中,数据转成二进制后不是直接以0101010的形式来表示的,而是用字节(bytes)类型来表示,当然对于人类来说不可读。在 Python 中可以使用 encode() 方法来进行转换,字符串转成 Bytes 类型如下所示

        在 Python 中,字符串必须编码成 Bytes 类型后才能存到硬盘上。回想一下,之前学的文件操作时也没有把字符串进行编码后再存储,但是也是可以正常进行存储的,那是因为 Python 默默就干了这个事,在 Python3 中文件存储的默认编码是 UTF-8,当然我们也可以自行改变文件的默认编码,这个需要在打开文件的时候对 encoding 参数进行设定,如下代码所示

f = open(file="encode_test.txt",mode="w",encoding="gbk")    # 这样写入的数据就是按 GBK 编码的了
f.write("世界和平")
f.close()

代码输出如下:

        在 PyCharm 中打开文件默认是使用 UTF-8 编码,当我们使用 UTF-8 编码的打开以 GBK 编码写入的文件时就会发现除了最后一行写入的英文字符外其他都是乱码,这种现象在字符编码时已经讲过了,如果还不明白可以再去翻看一下。当我们修改 PyCharm 把打开 encode_test.txt 的编码改为 GBK 时会发现一切又恢复了正常,如下图所示

三、以二进制模式操作文件

        有的同学就有疑问了,那我能不能不不用 open 这个对象来帮你自动编码呢?当然也可以直接往文件里存入 Bytes 数据,我们称之为二进制模式,这个模式分别有:wb(二进制创建)、rb(二进制读)、ab(二进制追加)

1、二进制创建

f = open('bytes_test.txt','wb')
f.write(b'\xca\xc0\xbd\xe7\xba\xcd\xc6\xbd\n')    # 直接写入已经编码好的二进制
f.write('世界和平\n'.encode('gbk'))    # 使用 encode() 对字符串进行编码,编码成 GBK
f.close()

代码输出如下:

2、二进制读

        二进制读在 read() 的时候并不会进行自动解码,而是会直接读取出以十六进制形式表现的字节串,这个时候需要使用 decode() 方法来进行解码后才能显示为人类看得懂的字符,后面会说到

f = open('bytes_test.txt','rb')
print(f.read())
f.seek(0)
print(f.read().decode('gbk'))
f.close()

代码输出如下: 

        在使用 decode() 的过程中很容易遇到以下报错:

UnicodeDecodeError: 'gbk' codec can't decode byte 0x88 in position 8: incomplete multibyte sequence
Unicode解码错误:“gbk”编解码器无法解码位置8的字节0x88:不完整的多字节序列

3、二进制追加

f = open('bytes_test.txt','ab')
f.write(b'\xca\xc0\xbd\xe7\xba\xcd\xc6\xbd3\n')
f.write('世界和平4\n'.encode('gbk'))
f.close()

代码输出如下:  

 

注意:以什么编码格式编写的文件必须以该编码格式来解码,例如在 Windows 就是 GBK,Mac 就是 UTF-8,不然你会看到全是乱码!

字符编码的转换

        编码转换是指将一种编码转成另外一种编码,例如 UTF-8 转换为 GBK 。为何需要编码转换呢?这是因为不同操作系统使用的编码不同,例如 Windows 上使用的是 GBK 编码,如果想要在 Windows 上查看则需要转成 GBK 才能正常显示,不然都是乱码没法看,反过来如果你的 GBK 编码的字符相对应在 Linux\Mac 上想正常显示,也就得转成 UTF-8 编码。

一、编码与解码

         编码与解码的代码如下

s = "世界和平"
print(s.encode("utf-8"))    # 编码
s_utf8 = s.encode("utf-8")
print(s_utf8.decode("utf-8"))    # 解码

 代码输出如下:

二、编码的转换 

        在 Python3 里,内存里的字符串是以 Unicode(万国码)编码的,Unicode 的其中一个特性就是跟所有语言编码都有映射关系。所以 UTF-8 格式的文件,在 Windows 电脑上若是不能看,就可以把 UTF-8 先解码成 Unicode,再由 Unicode 编码成 GBK 就可以了,如下图所示

注意:不管在 Windows、Mac、Linux 上,你的 Pycharm IDE 都可以支持各种文件编码,所以即使是 UTF-8 的文件,在 Windows 下的 PyCharm 里也可以正常显示

深浅 Copy

        这里的 Copy 其实就是字面的意思——复制,有的同学会发现,例如字符串的复制不是直接在被复制变量和被赋值变量之间加等号就可以了吗?这里忽略了一点,其实之前我们之前提过变量生成过程的时候就说过,像整数、浮点数和字符串这类不可修改的数据变量在改变其赋值时是直接重新生成一个,内存地址是会发生改变的,而列表、集合和字典这类可变的数据类型他是内存地址不变,即如果里面的变量修改变化了,变量名指向的内存地址也不会变化。我们可以用下面的代码进行验证

dict1 = {
    "name":"Jove",
    "age":18,
    "scores":{
        "语文":130,
        "数学":60,
        "英语":98,
    }
}

dict2 = dict1
print(id(dict1),id(dict2))
dict1["age"] = 20
print(dict2)
print(id(dict1),id(dict2))

代码输出如下: 

        从代码的执行结果可以看出 dict2 跟随 dict1 的修改而改变了,这是因为 dict2=dict1 相当于只是拿到了 dict1 的内存地址,但 dict1 里的每个 key 和 value 都是有单独的内存地址的,dict1 和 dict2 会一直共享这个 dict 里的数据,不会出现像字符串 a=1 b=8 a=2,最后 b 依然等于1的情况,如下图所示

        但是有的时候还是需要复制一份完全的 dict 数据呢?为了解决这个问题列表、集合和字典当中就存在了 copy() 和 deepcopy() 方法,而像元组这类不可变的变量就没有这类方法了。

一、浅 Copy

        上面提到的现象会不会有的同学会搞懵呢?我们再用通俗点的来描述一下这个现象,首先我们把字典这一个变量比作中国这个地方,那 dict1 就是一个名称,中文叫中国,英文叫 China,法文叫 La Chine 等等,只要别人叫出这个名称大家都知道是指这一个地方,而字典里面的变量就相当于中国里面的省,而第二层当中的就相当于市,如此类推。有一天中央下发了命令,需要彻底融合大湾区,需要把佛山、广州、中山、珠海、东莞等大湾区城市融合为一个广州湾区,这就相当于上面代码中 dict1["age"] = 20,那么这会不会影响别人叫中国、China、La Chine 是所指的地方呢?很明显,不会。其实这些可变变量也可以称为容器性质的数据类型,列表、集合、字典这些可变变量都有容器性质。

        而在想要复制他们时就需要使用到 copy() 方法,我们先来使用浅 Copy 来试下效果如何,代码如下

dict1 = {
    "name":"Jove",
    "age":18,
    "scores":{
        "语文":130,
        "数学":60,
        "英语":98,
    }
}

dict2 = dict1.copy()
dict1["age"] = 20
print("dict2:",dict2)
print("dict1:",dict1)

代码输出如下:

        这样就相当于是两份独立数据了,但是为什么这个语法叫做浅 Copy 呢?试一下改 scores 里的值就知道了,代码如下

dict1 = {
    "name":"Jove",
    "age":18,
    "scores":{
        "语文":130,
        "数学":60,
        "英语":98,
    }
}

dict2 = dict1.copy()
dict1["age"] = 20
dict1["scores"]["数学"] = 77
print("dict2:",dict2)
print("dict1:",dict1)

代码输出如下:

        看到这个输出很神奇吧,dict1 和 dict2 里的 age 的值是独立的,而 scores 里的字典的分数值却是共享的。这是因为浅 Copy 会仅复制 dict 的第一层数据,更深层的 scores 下面的值依然是共享一份,如下图所示

        这里要看清楚,图中的 dict1 和 dict2 中的 name 没有改变过所以内存地址是一样,在没改前这两个 name 都确实指向同一个内存地址,但只要改任何一个的值,内存地址都会变更,就像 age 一样。 而要克服这一困难就需要深 Copy 出场了。

二、深 Copy

        若想要彻底使上面的 dict1 和 dict2 完全独立(无论有多少层数据)。那就要用 Python 中的工具包里的一个工具了——copy,直接看代码

import copy

dict1 = {
    "name":"Jove",
    "age":18,
    "scores":{
        "语文":130,
        "数学":60,
        "英语":98,
    }
}

dict2 = copy.deepcopy(dict1)
dict3 = copy.copy(dict1)    # copy 工具包的 copy 和数据类型中的 copy 是一样的
dict1["age"] = 20
dict1["scores"]["数学"] = 77

print("dict1:",dict1)
print("dict2:",dict2)
print("dict3:",dict3)

代码输出如下:

        可以看得出 dict2 已经是完全将 dict1 完全复制了,并且修改 dict1 并不会影响到 dict2,但是用深 Copy 时需要注意存储空间,例如你的字典有 500Mb 这么大,如果使用深 Copy 的话就会需要 1Gb 这样会瞬间扩大一倍的存储空间,如果存储空间不足将会导致复制失败。 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ day07

C笔试题合集: 1、什么是虚函数?什么是纯虚函数? 1>在类中定义函数时,在函数名前加上virtual关键字,该函数就是虚函数,虚函数可以保证在父子类中只有一个该函数。 2>当虚函数头 0;时该函…

Killing LeetCode [416] 分割等和子集

Description 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 Intro Ref Link:https://leetcode.cn/problems/partition-equal-subset-sum/description/ Difficulty:Med…

【C++报错已解决】std::ios_base::sync_with_stdio

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

CSS——边框线条动画效果

CSS——边框线条动画效果 上次我们实现了边框的线条缩放效果,今天我们来用三种方式完成边框的线条旋转动态效果。 方法一:使用伪元素 这是最普遍、最常用的方法,我们需要为边框所在的元素添加伪元素,然后旋转这个伪元素即可。本…

OpenMV与STM32通信全面指南

目录 引言 一、OpenMV和STM32简介 1.1 OpenMV简介 1.2 STM32简介 二、通信协议概述 三、硬件连接 3.1 硬件准备 3.2 引脚连接 四、软件环境搭建 4.1 OpenMV IDE安装 4.2 STM32开发环境 五、UART通信实现 5.1 OpenMV端编程 5.2 STM32端编程 六、SPI通信实现 6.1 …

【蓝桥杯省赛真题55】Scratch找不同游戏 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解

scratch找不同游戏 第十五届青少年蓝桥杯scratch编程选拔赛真题解析 PS:其实这题在选拔赛里面就出现过类似的题目,只是难度提升了一点,具体可以见【蓝桥杯选拔赛真题84】Scratch找不同游戏 第十五届蓝桥杯scratch图形化编程 少儿编程创意编…

newbie难度——暴力枚举

newbie难度——暴力枚举 740 - 1743A 给出的样例能够理解,如果有n个数字不能选,要排四个数字,这四个数字只有两个不同,并且这两个相同的会各自出现两次,有6种排列方式,那如果给出小于样例n的数字&#xff…

电子电路智能设计课程内容是什么?

电子电路智能设计课程通常包括一系列内容,旨在教授学生如何使用现代电子设计自动化(EDA)工具和技术来设计和分析电子电路。 1. 电子设计自动化(EDA)概述: - EDA的历史和发展 - EDA在电子设计中的作用 - …

excel统计分析(2):描述统计工具

1.什么是【描述统计】工具 Excel中的描述性统计是指用于汇总和分析数据以更好地了解其特征的工具,方便快速了解数据集的中心趋势、离散程度和形状。 2.excel中添加【数据分析】功能 点击【文件>选项>加载项】,【管理>Excel加载项>转到】&…

SAP B1 认证考试习题 - 解析版(二)

前一篇:《SAP B1 认证考试习题 - 解析版(一)》 题目纯享版合集:《SAP B1 认证考试习题 - 纯享版》 三、采购流程 30. 下列哪个凭证在采购流程中是必须要完成的 A. 采购订单 B. 收货采购订单 C. 应付发票 D. 退货 E. 应付贷…

Vue项目快速整合WangEditor富文本编辑器

Vue项目快速整合WangEditor富文本编辑器 一、安装依赖 npm i wangeditor --save //富文本编辑器 npm install highlight.js -S //代码高亮 npm install dompurify vue-dompurify-html // 防xss 库二、app.vue代码案例 已对接图片、视频接口 ,具体看如下代码…

【Spring Cloud】Spring Cloud 概述

Spring Cloud 概述 1. 认识微服务1.1 单体架构1.2 集群和分布式架构集群和分布式 1.3 微服务架构分布式架构&微服务架构 1.4 微服务带来的挑战优势挑战 2. 微服务解决⽅案- Spring Cloud2.1 什么是Spring Cloud2.2 Spring Cloud版本Spring Cloud和SpringBoot的关系 2.3 Spr…

Linux部署RabbitMQ

目录 一、环境 二、开始安装 1、安装Erlang 2、安装RabbitMQ 3、修改配置文件 先复制覆盖配置文件,根据自己的版本进行路径更改 打开配置文件,53行 去掉注释%%和逗号 4、安装插件并启动服务 web管理界面工具 重新启动 RabbitMQ 服务 查看节点…

java日志门面之JCL和SLF4J

文章目录 前言一、JCL1、JCL简介2、快速入门3、 JCL原理 二、SLF4J1、SLF4J简介2、快速入门2.1、输出动态信息2.2、异常信息的处理 3、绑定日志的实现3.1、slf4j实现slf4j-simple和logback3.2、slf4j绑定适配器实现log4j3.2、Slf4j注解 4、桥接旧的日志框架4.1、log4j日志重构为…

什么是原生IP?

代理IP的各个类型称呼有很多,且它们在网络使用和隐私保护方面扮演着不同的角色。今天将探讨什么是原生IP以及原生IP和住宅IP之间的区别,帮助大家更好地理解这两者的概念和实际应用,并选择适合自己的IP类型。 一、什么是原生IP? 原…

流程、程序和政策之间的差异

流程、程序和政策是公司遵循的指导方针,以确保公司以有效和安全的方式运营。 每个企业都需要它们,但有时可能会让人搞不清一个从哪里开始,另一个从哪里结束。 企业经常混淆它们的用法,或者在真正含义上指错一个。 从高层次来看…

“数字武当”项目荣获2024年“数据要素×”大赛湖北分赛文化旅游赛道一等奖

9月26日,由国家数据局、湖北省人民政府指导的首届湖北省数据要素创新大会暨2024年“数据要素”大赛湖北分赛颁奖仪式在湖北武汉举行。由大势智慧联合武当山文化旅游发展集团有限公司参报的武当山“数字武当”项目,荣获文化旅游赛道一等奖。 据悉&#x…

《Linux从小白到高手》理论篇(三):vi/vim编辑器和Linux文件处理“三剑客”(sed/grep/awk)

List item 本篇介绍vi/vim编辑器和Linux文件处理“三剑客”(sed/grep/awk),这5个工具命令可能是Linux最最常用的,而且功能超级强大。 vi/vim vi和vim的基本介绍 所有的 Linux 系统都会内建 vi 文本编辑器。Vim 具有程序编辑的…

【frp】frp重启、frp启动、frp后台启动、frps dashboard等等

我写的关于frp配置的文章:frp配置 服务端frps 1. 创建服务文件 sudo nano /etc/systemd/system/frps.service2. 添加服务配置 在打开的文件中添加以下内容: [Unit] DescriptionFRPS Server Afternetwork.target[Service] Typesimple ExecStart/root…

LeetCode[简单] 136. 只出现一次的数字

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 思路 当 A 与 B 不同时,按…