参考链接: Python中的字节对象与字符串
1.常见字符串编码错误
在使用Python读文件时经常遇到编码问题引起的错误,比如:
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 30: illegal multibyte sequence
遇到这种异常时可以通过读文件时规定编码方式来解决,如下:
with open('zhengfu.txt','r',encoding='UTF-8') as read_zhengfu:
如果文件中还包含其他非UTF-8编码的字符,或者无关的特殊字符,可以再加入一个参数,如下:
with open('zhengfu.txt','r',encoding='UTF-8',errors='ignore') as read_zhengfu:
有时读文件时还会遇到一种问题就是第一行数据的开头多了一串‘'\ufeff’字符。比如:
如果用print(list[0])是看不到这个字符的。对这个没有研究过, 如果要去掉这串字符的话,可以使用‘utf-8-sig’这种编码方式:
with open('user_dict_2.txt','r',encoding='utf-8-sig') as read_dict:
但是我在写入文件时设置为‘utf-8-sig’格式时不起作用,写入的文件中还是有这个字符。
另外,在对字符串进行匹配的时候,'\ufeff’会影响字符串的匹配结果。
2.字符串编码
关于计算机内部如何表示字符串,为何又要创造这么多种编码方式,推荐阅读 https://www.cnblogs.com/hhwu/p/9529942.html 这篇博客里作者讲的很明白,这里主要是想汇总介绍Python中的字符串函数。
2.1 chr()函数和ord()函数
chr()函数是将一个整数返回一个对应的字符,ord()函数则相反,其返回一个字符的数值表示(返回的是Unicode值的十进制表示)。在Python3.6的版本中,chr()中整数的范围不再是0到255,扩大到了1114111,大于改值时,报ValueError错误。而ord()函数中只能接受单字符串作为其输入,否则会报TypeError错误。
print(chr(65)) #输出'A'
print(ord('A')) #输出65
2.2 Unicode编码
虽然Python 3的内存中Unicode来保存字符串,但为了节省内存,Python3内部使用3种方式存储Unicode字符。具体分为以下三种:
Latin-1一个字符占一个字节。比如ASCII码值UCS-2一个字符占两个字节。常见的中文都占用2个字节UCS-4一个字符占四个字节。比较偏僻的中文还有emoj表情通常占用4个字节。
python中提供了内置函数来查看每个字符串对象的编码类型。如果一个字符串的所有字符都能用ASCII码来表示,那么该字符串使用Latin-1。如果字符串中出现了中文,则采用UCS-2编码即可。如果字符串中有一些生僻字或者emoj表情的话,则必须使用UCS-4编码。注意在Python中,一个字符串中的所有字符只能采用一种编码方式,不能混用。因为一旦混用,那么字符串中每个字符所占的字节数必定不同,那么字符串将不能使用下标进行快速直接读取。下面来具体看看字符串具体在内存中所占用的字节数。
字符串的长度和该字符串所占的字节数不相同。字符串的长度可以直接通过len()f方法来求,而字符串在内存中实际所占的字节数需要通过getsizeof()函数来计算。
import sys
#返回字符串所占字节数,返回78
print(sys.getsizeof('你好'))
#返回字符串长度,长度为2
print(len("你好"))
从以下的实验结果可以发现,一个空字符串在内存中就占了49个字节的内存。
Python内存中的数据,不管是int型还是字符串,都会额外占用一些内存空间保存一些信息,这些信息保存了字符串的一些基础信息,并且能够决定字符串所能进行的操作。Python一般会为字符串分配49到80个字节的额外空间。
下面这段代码分别展示了字符‘a’在三种不用的Unicode编码中所占的字节数。
import sys
#latin-1编码时'a'所占的字节数,其结果为:1
print(sys.getsizeof('ab')-sys.getsizeof('b'))
#ucs-2编码时'a'所占的字节数,其结果为:2
print(sys.getsizeof('a你好')-sys.getsizeof('你好'))
#ucs-4编码时'a'所占的字节数,其结果为:4
print(sys.getsizeof('a?')-sys.getsizeof('?'))