Python中的字符串与字符编码

news2024/11/26 4:30:45

Hello,这里是Token_w的博客,欢迎您的到来
今天文章讲解的是Python中的字符串与字符编码,其中有基础的理论知识讲解,也有实战中的应用讲解,希望对你有所帮助
整理不易,如对你有所帮助,希望能得到你的点赞、收藏支持。感谢

目录

  • 一. 前言
  • 二. 相关概念
    • 2.1 字符与字节
    • 2.2 编码与解码
  • 三. Python中的默认编码
    • 3.1 Python源代码文件的执行过程
    • 3.2 默认编码
    • 3.3 最佳实践
  • 四. Python2与Python3中对字符串的支持
    • (1) Python2
    • (2) Python3
  • 五. 字符编码转换
  • 附六.字符编码
    • 1. ASCII码
    • 2. 扩展ASCII码(Extended ASCII)
    • 3. Unicode
    • 4. GB2312
    • 5. GBK
    • 6. GB18030
    • 7. UTF(UCS Transfer Format)
    • 8. 简单总结

一. 前言

Python中的字符编码是个老生常谈的话题,同行们都写过很多这方面的文章。有的人云亦云,也有的写得很深入。近日看到某知名培训机构的教学视频中再次谈及此问题,讲解的还是不尽人意,所以才想写这篇文字。一方面,梳理一下相关知识,另一方面,希望给其他人些许帮助。

Python2的 默认编码 是ASCII,不能识别中文字符,需要显式指定字符编码;Python3的 默认编码 为Unicode,可以识别中文字符。

相信大家在很多文章中都看到过类似上面这样“对Python中中文处理”的解释,也相信大家在最初看到这样的解释的时候确实觉得明白了。可是时间久了之后,再重复遇到相关问题就会觉得貌似理解的又不是那么清楚了。如果我们了解上面说的默认编码的作用是什么,我们就会更清晰的明白那句话的含义。

二. 相关概念

2.1 字符与字节

一个字符不等价于一个字节,字符是人类能够识别的符号,而这些符号要保存到计算的存储中就需要用计算机能够识别的字节来表示。一个字符往往有多种表示方法,不同的表示方法会使用不同的字节数。这里所说的不同的表示方法就是指字符编码,比如字母A-Z都可以用ASCII码表示(占用一个字节),也可以用UNICODE表示(占两个字节),还可以用UTF-8表示(占用一个字节)。字符编码的作用就是将人类可识别的字符转换为机器可识别的字节码,以及反向过程。

UNICDOE才是真正的字符串,而用ASCII、UTF-8、GBK等字符编码表示的是字节串。关于这点,我们可以在Python的官方文档中经常可以看到这样的描述"Unicode string" , " translating a Unicode string into a sequence of bytes"

我们写代码是写在文件中的,而字符是以字节形式保存在文件中的,因此当我们在文件中定义个字符串时被当做字节串也是可以理解的。但是,我们需要的是字符串,而不是字节串。一个优秀的编程语言,应该严格区分两者的关系并提供巧妙的完美的支持。JAVA语言就很好,以至于了解Python和PHP之前我从来没有考虑过这些不应该由程序员来处理的问题。遗憾的是,很多编程语言试图混淆“字符串”和“字节串”,他们把字节串当做字符串来使用,PHP和Python2都属于这种编程语言。最能说明这个问题的操作就是取一个包含中文字符的字符串的长度:

  • 对字符串取长度,结果应该是所有字符串的个数,无论中文还是英文
  • 对字符串对应的字节串取长度,就跟编码(encode)过程使用的字符编码有关了(比如:UTF-8编码,一个中文字符需要用3个字节来表示;GBK编码,一个中文字符需要2个字节来表示)
    注意:Windows的cmd终端字符编码默认为GBK,因此在cmd输入的中文字符需要用两个字节表示
# Python2
a = 'Hello,中国'  # 字节串,长度为字节个数 = len('Hello,')+len('中国') = 6+2*2 = 10
b = u'Hello,中国'  # 字符串,长度为字符个数 = len('Hello,')+len('中国') = 6+2 = 8
c = unicode(a, 'gbk')  # 其实b的定义方式是c定义方式的简写,都是将一个GBK编码的字节串解码(decode)为一个Uniocde字符串

print(type(a), len(a))
# (<type 'str'>, 10)
print(type(b), len(b))
# (<type 'unicode'>, 8)
print(type(c), len(c))
# (<type 'unicode'>, 8)

Python3中对字符串的支持做了很大的改动,具体内容会在下面介绍。

2.2 编码与解码

先做下科普:UNICODE字符编码,也是一张字符与数字的映射,但是这里的数字被称为代码点(code point), 实际上就是十六进制的数字。

Python官方文档中对Unicode字符串、字节串与编码之间的关系有这样一段描述:

Unicode字符串是一个代码点(code point)序列,代码点取值范围为0到0x10FFFF(对应的十进制为1114111)。这个代码点序列在存储(包括内存和物理磁盘)中需要被表示为一组字节(0到255之间的值),而将Unicode字符串转换为字节序列的规则称为编码。

这里说的编码不是指字符编码,而是指编码的过程以及这个过程中所使用到的Unicode字符的代码点与字节的映射规则。这个映射不必是简单的一对一映射,因此编码过程也不必处理每个可能的Unicode字符,例如:

将Unicode字符串转换为ASCII编码的规则很简单–对于每个代码点:

  • 如果代码点数值<128,则每个字节与代码点的值相同

  • 如果代码点数值>=128,则Unicode字符串无法在此编码中进行表示(这种情况下,Python会引发一个UnicodeEncodeError异常)
    将Unicode字符串转换为UTF-8编码使用以下规则:

  • 如果代码点数值<128,则由相应的字节值表示(与Unicode转ASCII字节一样)

  • 如果代码点数值>=128,则将其转换为一个2个字节,3个字节或4个字节的序列,该序列中的每个字节都在128到255之间。
    简单总结:

  • 编码(encode):将Unicode字符串(中的代码点)转换特定字符编码对应的字节串的过程和规则

  • 解码(decode):将特定字符编码的字节串转换为对应的Unicode字符串(中的代码点)的过程和规则
    可见,无论是编码还是解码,都需要一个重要因素,就是特定的字符编码。因为一个字符用不同的字符编码进行编码后的字节值以及字节个数大部分情况下是不同的,反之亦然。

三. Python中的默认编码

3.1 Python源代码文件的执行过程

我们都知道,磁盘上的文件都是以二进制格式存放的,其中文本文件都是以某种特定编码的字节形式存放的。对于程序源代码文件的字符编码是由编辑器指定的,比如我们使用Pycharm来编写Python程序时会指定工程编码和文件编码为UTF-8,那么Python代码被保存到磁盘时就会被转换为UTF-8编码对应的字节(encode过程)后写入磁盘。当执行Python代码文件中的代码时,Python解释器在读取Python代码文件中的字节串之后,需要将其转换为UNICODE字符串(decode过程)之后才执行后续操作。

上面已经解释过,这个转换过程(decode,解码)需要我们指定文件中保存的字节使用的字符编码是什么,才能知道这些字节在UNICODE这张万国码和统一码中找到其对应的代码点是什么。这里指定字符编码的方式大家都很熟悉,如下所示:

# -*- coding:utf-8 -*-

在这里插入图片描述

3.2 默认编码

那么,如果我们没有在代码文件开始的部分指定字符编码,Python解释器就会使用哪种字符编码把从代码文件中读取到的字节转换为UNICODE代码点呢?就像我们配置某些软件时,有很多默认选项一样,需要在Python解释器内部设置默认的字符编码来解决这个问题,这就是文章开头所说的“默认编码”。因此大家所说的Python中文字符问题就可以总结为一句话:当无法通过默认的字符编码对字节进行转换时,就会出现解码错误(UnicodeEncodeError)。

Python2和Python3的解释器使用的默认编码是不一样的,我们可以通过sys.getdefaultencoding()来获取默认编码:

# Python2
import sys
print(sys.getdefaultencoding() )
# 'ascii'

# Python3
import sys
print(sys.getdefaultencoding() )
# 'utf-8'

因此,对于Python2来讲,Python解释器在读取到中文字符的字节码尝试解码操作时,会先查看当前代码文件头部是否有指明当前代码文件中保存的字节码对应的字符编码是什么。如果没有指定则使用默认字符编码"ASCII"进行解码导致解码失败,导致如下错误:

SyntaxError: Non-ASCII character '\xc4' in file xxx.py on line 11, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

对于Python3来讲,执行过程是一样的,只是Python3的解释器以"UTF-8"作为默认编码,但是这并不表示可以完全兼容中文问题。比如我们在Windows上进行开发时,Python工程及代码文件都使用的是默认的GBK编码,也就是说Python代码文件是被转换成GBK格式的字节码保存到磁盘中的。Python3的解释器执行该代码文件时,试图用UTF-8进行解码操作时,同样会解码失败,导致如下错误:

SyntaxError: Non-UTF-8 code starting with '\xc4' in file xxx.py on line 11, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

3.3 最佳实践

  • 创建一个工程之后先确认该工程的字符编码是否已经设置为UTF-8
  • 为了兼容Python2和Python3,在代码头部声明字符编码:-- coding:utf-8 --

四. Python2与Python3中对字符串的支持

其实Python3中对字符串支持的改进,不仅仅是更改了默认编码,而是重新进行了字符串的实现,而且它已经实现了对UNICODE的内置支持,从这方面来讲Python已经和JAVA一样优秀。下面我们来看下Python2与Python3中对字符串的支持有什么区别:

(1) Python2

Python2中对字符串的支持由以下三个类提供

class basestring(object)
    class str(basestring)
    class unicode(basestring)

执行help(str)和help(bytes)会发现结果都是str类的定义,这也说明Python2中str就是字节串,而后来的unicode对象对应才是真正的字符串。

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

a = '你好'
b = u'你好'

print(type(a), len(a))
print(type(b), len(b))

输出结果:

(<type 'str'>, 6)
(<type 'unicode'>, 2)

(2) Python3

Python3中对字符串的支持进行了实现类层次的上简化,去掉了unicode类,添加了一个bytes类。从表面上来看,可以认为Python3中的str和unicode合二为一了。

class bytes(object)
class str(object)

实际上,Python3中已经意识到之前的错误,开始明确的区分字符串与字节。因此Python3中的str已经是真正的字符串,而字节是用单独的bytes类来表示。也就是说,Python3默认定义的就是字符串,实现了对UNICODE的内置支持,减轻了程序员对字符串处理的负担。

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

a = '你好'
b = u'你好'
c = '你好'.encode('gbk')

print(type(a), len(a))
print(type(b), len(b))
print(type(c), len(c))

输出结果:

<class 'str'> 2
<class 'str'> 2
<class 'bytes'> 4

五. 字符编码转换

上面提到,UNICODE字符串可以与任意字符编码的字节进行相互转换,如图:
在这里插入图片描述
那么大家很容易想到一个问题,就是不同的字符编码的字节可以通过Unicode相互转换吗?答案是肯定的。

Python2中的字符串进行字符编码转换过程是:
字节串–>decode(‘原来的字符编码’)–>Unicode字符串–>encode(‘新的字符编码’)–>字节串

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


utf_8_a = '我爱中国'
gbk_a = utf_8_a.decode('utf-8').encode('gbk')
print(gbk_a.decode('gbk'))

输出结果:

我爱中国

Python3中定义的字符串默认就是unicode,因此不需要先解码,可以直接编码成新的字符编码:
字符串–>encode(‘新的字符编码’)–>字节串

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


utf_8_a = '我爱中国'
gbk_a = utf_8_a.encode('gbk')
print(gbk_a.decode('gbk'))

输出结果:

我爱中国
最后需要说明的是,Unicode不是有道词典,也不是google翻译器,它并不能把一个中文翻译成一个英文。正确的字符编码的转换过程只是把同一个字符的字节表现形式改变了,而字符本身的符号是不应该发生变化的,因此并不是所有的字符编码之间的转换都是有意义的。怎么理解这句话呢?比如GBK编码的“中国”转成UTF-8字符编码后,仅仅是由4个字节变成了6个字节来表示,但其字符表现形式还应该是“中国”,而不应该变成“你好”或者“China”。

前面花了很大的篇幅介绍概念和理论,后面注重实践,希望对您有所帮助。

附六.字符编码

1. ASCII码

ASCII码是美国早期制定的编码规范,只能表示128个字符,包括英文字符、阿拉伯数字、西文字符以及32个控制字符。简单来说,就是下面这个表:
在这里插入图片描述

2. 扩展ASCII码(Extended ASCII)

简单而言,扩展ASCII码的出现是因为ASCII不够用,所以向ASCII表继续扩充到256个符号。 但是因为对于扩展ASCII,不同的国家有不同的标准,于是促使了Unicode编码的诞生。 扩展ASCII码表如下:
在这里插入图片描述

3. Unicode

准确来说,Unicode不是编码格式,而是字符集。这个字符集包含了世界上目前所有的符号。 另外,在原来有些字符可以用一个字节即8位来表示的,在Unicode将所有字符的长度全部统一为16位,因此字符是定长的。 Unicode是长这样的:

\u4f60\u597d\u4e2d\u56fd\uff01\u0068\u0065\u006c\u006c\u006f\uff0c\u0031\u0032\u0033

上面这段Unicode的意思是“你好中国!hello,123”。

关于Unicode,可在这个网站查到所有字符: https://unicode-table.com/en/
在这里插入图片描述
在这里插入图片描述

4. GB2312

当国人得到计算机后,那就要对汉字进行编码。在ASCII码表的基础上,小于127的字符意义与原来相同;而将两个大于127的字节连在一起,来表示汉字,前一个字节从0xA1(161)到0xF7(247)共87个字节,称为高字节,后一个字节从0xA1(161)到0xFE(254)共94个字节,称为低字节,两者可组合出约8000种组合,用来表示6763个简体汉字、数学符号、罗马字母、日文字等。 在重新编码的数字、标点、字母是两字节长的编码,这些称为“全角”字符;而原来在ASCII码表的127以下的称为“半角”字符。 简单而言,GB2312就是在ASCII基础上的简体汉字扩展。

gb2312码表: http://www.fileformat.info/info/charset/GB2312/list.htm

5. GBK

简单而言,GBK是对GB2312的进一步扩展(K是汉语拼音kuo zhan(扩展)中“扩”字的声母), 收录了21886个汉字和符号,完全兼容GB2312。

6. GB18030

GB18030收录了70244个汉字和字符,更加全面,与 GB 2312-1980 和 GBK 兼容。 GB18030支持少数民族的汉字,也包含了繁体汉字和日韩汉字。 其编码是单、双、四字节变长编码的。

7. UTF(UCS Transfer Format)

UTF是在互联网上使用最广的一种Unicode的实现方式。我们最常用的是UTF-8,表示每次8个位传输数据,除此之外还有UTF-16。

UTF-8长这样,“你好中国!hello,123”:

你好中国!hello,123

8. 简单总结

  • 中国人民通过对 ASCII 编码的中文扩充改造,产生了 GB2312 编码,可以表示6000多个常用汉字。
  • 汉字实在是太多了,包括繁体和各种字符,于是产生了 GBK 编码,它包括了 GB2312 中的编码,同时扩充了很多。
  • 中国是个多民族国家,各个民族几乎都有自己独立的语言系统,为了表示那些字符,继续把 GBK 编码扩充为 GB18030 编码。
  • 每个国家都像中国一样,把自己的语言编码,于是出现了各种各样的编码,如果你不安装相应的编码,就无法解释相应编码想表达的内容。
  • 终于,有个叫 ISO 的组织看不下去了。他们一起创造了一种编码 UNICODE ,这种编码非常大,大到可以容纳世界上任何一个文字和标志。所以只要电脑上有 UNICODE 这种编码系统,无论是全球哪种文字,只需要保存文件的时候,保存成 UNICODE 编码就可以被其他电脑正常解释。
  • UNICODE 在网络传输中,出现了两个标准 UTF-8 和 UTF-16,分别每次传输 8个位和 16个位。于是就会有人产生疑问,UTF-8 既然能保存那么多文字、符号,为什么国内还有这么多使用 GBK 等编码的人?因为 UTF-8 等编码体积比较大,占电脑空间比较多,如果面向的使用人群绝大部分都是中国人,用 GBK 等编码也可以。

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

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

相关文章

Linux怎样处理网络请求——彻底理解IO多路复用

常见的网络IO模型 网络 IO 模型分为四种&#xff1a;同步阻塞 IO、同步非阻塞IO、IO 多路复用、异步非阻塞 IO(Async IO, AIO)&#xff0c;其中AIO为异步IO&#xff0c;其他都是同步IO 同步阻塞IO 同步阻塞IO&#xff1a;在线程处理过程中&#xff0c;如果涉及到IO操作&…

计算机竞赛 python+opencv+机器学习车牌识别

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于机器学习的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;3分 该项目较为新颖&#xff0c;适…

设计HTML5表单

HTML5基于Web Forms 2.0标准对HTML4表单进行全面升级&#xff0c;在保持简便、易用的基础上&#xff0c;新增了很多控件和属性&#xff0c;从而减轻了开发人员的负担。表单为访问者提供了与网站进行互动的途径&#xff0c;完整的表单一般由控件和脚本两部分组成。 1、认识HTML…

boss直聘投简历的时候会使用的一些功能

切换地区选择自己要工作的区域 点击在线简历 --> 求职期望里面可以设置工作城市 屏蔽掉之前离职过的公司 点击设置 --> 点击隐私保护 我们最好这里手动屏蔽掉之前入职的公司 这个页面还支持设置Boss查看权限&#xff0c;屏蔽职类(比如不看中介的职位&#xff0c;不…

JetBrains学生正版全家桶授权(大学4年免费)获取教程-idea学生免费许可解决方法

JetBrains学生正版全家桶授权&#xff08;大学4年免费&#xff09;获取教程 文章目录 JetBrains学生正版全家桶授权&#xff08;大学4年免费&#xff09;获取教程一、学信网二、JetBrains学生认证三、idea下载四、idea添加许可证 一、学信网 1.打开学信网&#xff08;中国高等…

免费在线 GIF 制作器和图像编辑器

hi&#xff0c;大家好我是技术苟&#xff0c;每天晚上22点准时上线为你带来实用黑科技&#xff01;由于公众号改版&#xff0c;现在的公众号消息已经不再按照时间顺序排送了。因此小伙伴们就很容易错过精彩内容。喜欢黑科技的小伙伴&#xff0c;可以将黑科技百科公众号设为标星…

MySQL8安装和删除教程 下载源码 保姆级(Windows)

删除 停止Mysql服务 管理员的权限来运行cmd&#xff0c;输入 net stop MySQL80 注意你电脑上的MySQL服务不一定是MySQL80,MySQL80是默认的&#xff0c;不是怎么办?在services.msc中找即可 下载一个小工具 geek:Geek下载打开软件&#xff0c;在列表中找到图片中的两项 sc…

ViewFs And Federation On HDFS

序言 ViewFs 是在Federation的基础上提出的,用于通过一个HDFS路径来访问多个NameSpace,同时与ViewFs搭配的技术是client-side mount table(这个就是具体的规则配置信息可以放置在core.xml中,也可以放置在mountTable.xml中). 总的来说ViewFs的其实就是一个中间层,用于去连接不…

Springboot项目启动后按顺序加载自定义类 (demo)

1. 实现ApplicationRunner接口, 重写run方法 import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.annotation.Order; import org.springframewor…

HoudiniVex笔记_P22_RemappingBasics重映射

原视频&#xff1a;https://www.youtube.com/playlist?listPLzRzqTjuGIDhiXsP0hN3qBxAZ6lkVfGDI Bili&#xff1a;Houdini最强VEX算法教程 - VEX for Algorithmic Design_哔哩哔哩_bilibili Houdini版本&#xff1a;19.5 1、fit函数 取范围(omin&#xff0c;omax)中的值&am…

Netty:ByteBuf的资源释放方法

说明 io.netty.buffer.ByteBuf实现了io.netty.util.ReferenceCounted接口&#xff0c;需要显式释放。当ByteBuf被实例化后&#xff0c;它的引用计数是1。 调用ByteBuf对象的release方法释放&#xff1a; ByteBuf的release()方法使引用计数减少1。只有当执行以后引用计数减少…

【运维】linkis安装dss保姆级教程与踩坑实践

文章目录 一. 安装准备二. 创建用户三. 准备安装包四. 修改配置1. 修改config.sh2. 修改db.sh 五、安装和使用1. 执行安装脚本2. 启动服务3. 查看验证是否成功 六. 报错处理报错一&#xff1a;The user is not logged in报错二&#xff1a;dss接口报错报错三&#xff1a;执行没…

bigemap如何添加arcgis地图?

批量添加视频教程 相关链接&#xff1a;添加卫星影像图 教程 说明&#xff1a;批量添加可以同时添加多个在线地图&#xff0c;一次性添加完成&#xff08;批量添加无法验证地址是否可以访问&#xff09; 添加后如下图&#xff1a; 第一步 &#xff1a; 制作地图配置文件&…

从小白到大神之路之学习运维第80天-------Kubernetes企业级高可用集群部署

第四阶段 时 间&#xff1a;2023年8月14日 参加人&#xff1a;全班人员 内 容&#xff1a; Kubernetes 企业级高可用部 目录 一、Kubernetes高可用项目介绍 二、项目架构设计 &#xff08;一&#xff09;项目主机信息 &#xff08;二&#xff09;项目架构图 &#…

私域流量运营的软件终点是App?

2023年&#xff0c;中国新生人口出生人数预测只有780W&#xff0c;少得可怜。微信、支付宝、抖音、小红书等社交平台&#xff0c;在21世纪20年代风生水起&#xff0c;伴随者人口红利的增长&#xff0c;奠定了中国公域流量平台的位置。 市场是千变万化的。人口急剧缩减&#xf…

力扣:63. 不同路径 II(Python3)

题目&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。那么从…

企业流程化管理有什么好处?企业实现流程化管理需要哪些步骤?

在当今快速发展的商业环境中&#xff0c;企业需要一个高效、可靠的管理系统来支持其日常运营和持续发展。流程管理作为一种系统化的管理方法&#xff0c;通过对工作流程的标准化、规范化、透明化等手段&#xff0c;使企业管理更具针对性、效率性和可控性。本文将通过介绍流程管…

【100天精通python】Day35:一文掌握GUI界面编程基本操作

目录 专栏导读 1 GUI 编程概述 1.1 为什么需要GUI&#xff1f; 1.2 常见的GUI编程工具和库 1.3 GUI应用程序的组成和架构 2 使用Tkinter 库 进行GUI编程 2.1 使用Tkinter库进行GUI编程的基本流程 2.2 使用Tkinter库进行GUI编程 2.2.1 导入Tkinter库 2.2.2 添加标签和…

TCP/IP协议追层分析物理层(第三十九课)

TCP/IP协议追层分析物理层(第三十九课) 1 物理层:建立、维护、断开物理连接,定义了接口及介质,实现了比特流的传输。 1、传输介质分类 有线介质:网线(双绞线)、光纤 无线介质:无线电 微波 激光 红外线 2、双绞线分类: 五类cat5: 适用于100Mbps 超五类cat5e:适用于…

深入源码分析kubernetes informer机制(二)Reflector

[阅读指南] 这是该系列第二篇 基于kubernetes 1.27 stage版本 为了方便阅读&#xff0c;后续所有代码均省略了错误处理及与关注逻辑无关的部分。 文章目录 Reflector是什么整体结构工作流程list拉取数据缓存resync操作watch监听操作 总结 Reflector是什么 reflector在informer…