字符串也是一种数据类型,但比较特殊的是字符串存在一个编码问题,也就是我们怎么用计算机来表示相应的字符并存储。在编程语言中,我们经常会处理文本编码之间的转化问题,因为文本可能存在不同的编码,比如 ASCII、GBK、UTF-8 等等。

如果希望正确的处理文本,就必须了解字符的抽象概念。我们可以认为字符表示的是文本中的单个符号。更重要的是,一个字符不是一个字节。比如,"中"在文本中是一个字符,但它存储在计算机中时却不是一个字节。一个字符有许多表示方法,不同的表示方法会使用不同的字节数,这就是所谓的编码。字符就是文本中最小的单元。

由于计算机是美国人发明的,因此,最早只有 127 个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为 ASCII 编码。但是计算机被广泛应用之后,ASCII 编码已经不足以表示世界上的各种语言,于是后来便出现了 Unicode 编码。

Unicode 是一种编码规范, 用来统一表示世界上的各种语言。Unicode 只是规定如何编码,并没有规定如何传输和保存等等,因此 Unicode 编码有不同的实现方式,比如:UTF-8、UTF-16 。UTF-8 编码把一个 Unicode 字符根据不同的数字大小编码成 1-6 个字节,常用的英文字母被编码成 1 个字节,汉字通常是 3 个字节,只有很生僻的字符才会被编码成 4-6 个字节。Unicode 以大家都认可的方式定义了一系列的字符,可以将其理解成一个字符数据库,每个字符都与唯一的数字关联,称为 code point。这样,英文大写字母 A 的 codepoint 是 U+0041,而欧元符号的 codepoint 是 U+20A0。一个文本字符串就是一系列的 code point,表示字符串中每个字符元素。

Python 由荷兰人 Guido van Rossum 于 1989 年发明,第一个公开发行版发行于 1991 年。Guido 在设计之初并没有关心编码问题(当时他也不知道后来会出现编码问题), 而且 Python 的诞生比 Unicode 标准发布的时间要早,因此 Python 默认编码在 Python3 之前是 ASCII。查看 Python 的默认编码:

>>> import sys

>>> sys.getdefaultencoding()

'ascii'

这么默认编码有什么用呢?如果你在 Python 中进行编码和解码的时候,不指定编码方式,那么 Python 就会使用 defaultencoding。

字符串在 Python 内部的表示是 Unicode 编码, 在 Python 内部使用两个字节来存储一个 Unicode。也就是 Python 在内存中统一使用 Unicode 编码存储字符数据,当需要保存到硬盘或者需要传输的时候,就转换为其他编码,比如 UTF-8。

在 Python2 中,字符串的类型有两种,即 str 和 unicode,他们都是 basestring 的子类。unicode 表示 Unicode 字符串(文本字符串),str 表示字节字符串(二进制数据),由 unicode 经过编码后的字节组成。也就是说:

str 存储的是已经编码后的字节序列,输出时看到每个字节用 16 进制表示,以\x开头。每个汉字会占用3个字节的长度。

unicode 是“字符”串,存储的是编码前的字符,输出时看到字符以\u开头。每个汉字占用一个长度。定义一个 Unicode 对象时,以 u 开头。

在 Python 中 Unicode 被视为是一种中间码,如果要在不同的编码间进行转化,通常是先将字符串解码(decode)成 Unicode 编码,再从 Unicode 编码(encode)成另一种编码:

decode: 的作用是将其他编码的字符串转换成 Unicode 编码,例如: name.decode(“GB2312”),表示将 GB2312 编码的字符串 name 转换成 Unicode 编码

encode: 的作用是将 Unicode 编码转换成其他编码的字符串例如,例如: name.encode(”GB2312“),表示 Unicode 编码的字符串 name 转换成 GB2312 编码

我们会在很多 Python 的源码文件的头部看到如下的声明:

# coding: utf-8

这表示声明源代码中的文本编码为 UTF-8,也就是告诉 Python 解释器将文件中的文本视为 UTF-8 编码的字符串,因此声明的编码应该与文件的编码保持一致。在代码中我们通常会处理一些其他来源的文本,比如网络,它们的编码不一定也是 UTF-8 的,因此就要进行编码转换。

Python 试图在字节串和字符串之间以不为人所察觉的方式进行转化。在不同的转换中,在条件允许的情况下,Python 会试图在字节串和 unicode 字符串直接进行转换。例如将字节串和 unicode 字节串连接到一起时。但是不使用 encoding 就在不同类型之间进行转换是没有意义的。所以 Python 依赖一个 默认编码,该编码由 sys.setdefaultencoding() 指定。在大多数平台上,默认的是 ASCII 编码。但对于所有转换,使用这种编码几乎都是错误的。如果不手动指定编码就调用 str() 或 unicode() ,或是函数以字符串作为参数,但传递的是其他类型的参数时,都会使用这个默认编码。这就是很多时候出现 UnicodeEncodeError 和 UnicodeDecodeError 错误的原因,也就是 字符串对象互相转化时没有指定字符编码。

例如,如果对 unicode 和 str 类型通过 + 拼接时,输出结果是 unicode 类型,相当于先将 str 类型的字符串通过 decode() 方法解码成 unicode 再拼接。此时如果解码时没有明确指明编码类型,可能会出现错误。

解决这个问题的一个办法是,调用 sys.setdefaultencoding() 将默认的编码设置为真正会用到的编码。但这样仅仅是将问题隐藏起来,虽然这样刚开始能解决一些文本处理问题。但缺乏实际可行性,因为许多应用,特别是网络应用,在不同的地方会使用不同的文本编码。

要注意的一点是,对 Unicode 进行编码和对 str 进行编码都是错误的。即不要对 str 使用 encode,不要对 unicode 使用 decode(事实上可以对 str 进行 encode 的,但不建议)。

下面是一些处理 Python 中字符编码的建议:

所有文本字符串都应该是 unicode 类型,而不是 str 类型。

若要将字节串解码成字符串,需要使用正确的解码,即 var.decode(encoding),如: var.decode('utf-8');将文本字符串编码成字节,使用 var.encode(encoding)。

永远不要对 unicode 字符串使用 str() ,也不要在不指定编码的情况下就对字节串使用 unicode() 。

当应用从外部读取数据时,应将其视为字节串,即 str 类型的,接着调用 .decode() 将其解释成文本。同样,在将文本发送到外部时,总是对文本调用 .encode()。

对标准流进行操作时,可以改变环境变量 PYTHONIOENCODING 的值来设置标准流的默认编码, sys.stdin.encoding 和 sys.stdout.encoding 的值为期望的编码。

以上内容的讨论都仅限于 Python2,在 Python3 中已经修复了这些问题,可以正确的处理 unicode 和字符串。

参考资料:

python查看字符编码值_Python 字符编码相关推荐

  1. 用python查看和更改系统默认编码

    用python查看和更改系统默认编码 python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错UnicodeDecodeError: 'asci ...

  2. 字符编码在python中的处理_python 字符编码处理问题总结

    Python中常常遇到这种字符编码问题,尤其在处理网页源代码时(特别是爬虫中): UnicodeDecodeError: 'XXX' codec can't decode bytes in posit ...

  3. 字符编码在python中的处理_Python 字符编码处理总结

    Python中经常遇到这样那样的字符编码问题,尤其在处理网页源码时(特别是爬虫中): UnicodeDecodeError: 'XXX' codec can't decode bytes in pos ...

  4. python 字符图_python 字符画

    教你利用Python把图片转字符画!代码哆啦A梦你见过嘛? 图片转字符画的关键是把图片的灰度值与自定义的字符集之间建立映射关系,不同区间的灰度值对应不同的字符,之后将图片每一个像素对应的字符打印出来, ...

  5. python 查看数据结构类型_python 数据结构类型总结(示例代码)

    文章目录 字符串: 1.用引号来创建字符串,单双引号都可(三引号也可:三引号可以复制复杂的字符串,三引号内一个字符串可占多行,字符串中可包含换行符.制表符和其他特殊字符). eg. >>& ...

  6. python 查看文件编码格式_python查看与改变文件的编码格式

    python查看与改变文件的编码格式 查看文件的编码格式 with open(r"C:\Users\Administrator\Desktop\111\2.1 (1)smile.txt&qu ...

  7. python视频转字符动画_python字符动画

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! python3 & opencv 视频转字符动画本课程使用 opencv ...

  8. python 读中文乱码_python字符乱码的解决小结

    引言 无论学习什么程序语言,字符串这种数据类型总是着有非常重要.然而最近在学习python这门语言,想要显示中文,总是出现各种乱码.于是在网上查了很多资料,各说纷纭,我也尝试了许多的方法,有时候可以正 ...

  9. python二进制转换为转义字符_Python字符与进制转换

    Python字符与进制转换 0b / 0B --> 二进制字符前缀 0o / 0O --> 八进制字符前缀 0x / 0X --> 十六进制字符前缀 ascii(object) 就 ...

  10. python字符型_python字符类型

    1.整型(Int) Int,整数,范围为 -2 ** 31 到 2 ** 31 - 1 ,超出这个范围便是长整型,有2进制,8进制,10进制,16进制.用8进制表示整数时,前面要加'0'的前缀,16进 ...

最新文章

  1. java 任意多个整数相加_一个整数分为若干个连续整数之和(使用java实现)
  2. B - Linear Algebra Test————只给思路
  3. 数据库系统概论:第十一章 并发控制
  4. shell编程-实现线性筛
  5. Java jdbctemplate赋值_JDBCTemplate基本使用
  6. 《城邦暴力团》:一部奇书、反书、隐书
  7. 世界上最美的40个小镇,你见过多少个?
  8. 【JS新手教程】LODOP打印复选框选中的任务或页数
  9. 团队作业4——第一次项目冲刺(Alpha版本)4.25
  10. java BorderLatout_浅谈java的BorderLayout的使用
  11. WebRTC服务器——Licode 环境搭建
  12. 声纹识别技术的现状、局限与趋势
  13. 关于vs编译的程序无法正常启动(0xc0150002)的问题
  14. Shell 编程实践
  15. dockerexec 的使用-it操作
  16. 方叫兽教你如何正确的赚钱
  17. 微信小程序云开发csv导入数据库中文乱码问题解决
  18. JS实现计算器,带三角函数,根号(伍)
  19. 织梦文章摘要php文件,织梦dedecms自动采集文章摘要教程
  20. 把多个txt文档合并为一个txt文档并排序

热门文章

  1. 切比雪夫不等式例题讲解_人教版初中数学七年级下册一元一次不等式组公开课优质课课件教案视频...
  2. es like模糊匹配_Elastic search模糊匹配,精确匹配显示在前
  3. 天天生鲜项目需求分析——基于Django框架的天天生鲜电商网站项目系列博客(一)...
  4. Android Studio内置JDK源码关联和断点错乱问题解决
  5. 常用编程语言简介大全
  6. html在线取色,JS实现的RGB网页颜色在线取色器完整实例
  7. 超神能力:云库局面分析
  8. 游戏必备组件_电脑必备软件~强大到~ 相识恨晚的感觉
  9. java单线程爬虫使用Jsoup爬取bt磁力链接
  10. plsqldev、oracle插入中文乱码问题解决