Python中关于coding=utf-8以及中文字符前加u的解释

本文深入探讨了Python中编码声明的重要性,特别是在处理中文字符时。文章详细解释了UTF-8编码的作用及如何正确声明,并介绍了Unicode编码的基本原理及其在Python字符串处理中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写了很久的Python了,每次写之前都要在开头加上coding=utf-8,只知道是设置编码格式,但并没有太在意,今天在写socket编程时才发现编码格式的重要性。

一、关于开头coding=utf-8

开头的coding=utf-8和coding:utf-8的作用是一样的。

它们的作用都是声明python代码的文本格式是utf-8编码的,也即告诉python解释器要按照utf-8编码的方式来读取程序。

如果不加这个声明,无论代码中还是注释中有中文都会报错。

以下几种方式都可以:

# coding=utf-8

a = 10
print '这是内容'
# coding:utf-8

a = 10
print '这是内容'

注意一点无论中间是:还是=,其中coding与它们之间都不能有空格。否则也会报错。

注意:以上是针对Python2.x的版本而言,因为在Python2.x的版本中文本默认采用的是ASCII编码方式,而Python3.x的版本中,默认使用的就是UTF-8编码格式,所以就不需要在前面进行声明了。

二、关于中文字符前面的u

首先,我们先从最开始的ASCII编码开始说起,我们知道计算机在处理程序时是看不懂文字的,它眼里只有0/1数字。所以最开始的ASCII编码是通过1个字节也就是8bit来表示英文字符。因为8个二进制位可以表示出256中状态,所以用来表示英文字符绰绰有余,因此ASCII码只用到了8个二进制中的后七位,也就是可以得到128个字符。

但是像一些其他语言的字符想通过最多只能表示256个字符的ASCII编码来表示就不太实际了。我们中华文明博大精深,光汉字就有超过6万多,所以必须有一种可以表示更多字符的编码方式,如常见的GB2312编码方式,它是通过两个字节来表示一个汉字,这样最多就可以表示256*256=65536个字符了。

而由于GB2312不能处理一些古汉语或者人名中的一些罕见字,所以导致了后面的GBK编码GB18030编码方式的出现。其中,GBK也是双字节的编码方式,并且GBK字符集中共收入了21886个汉字和图像符号。除此之外,GBK还可以与GB 2312完全兼容。

既然对于每种语言都有其对应的字符集,那么是否存在一种字符集可以包含世界上所有的符号呢。所以产生了Unicode编码。Unicode编码为世界上所有的语言的每个字符都设定了唯一的二进制编码,这样就可以实现跨语言进行文本转换和传输了。

通过Unicode进行编码时,不同字符所占用的位的长度是不同的,也就是说有的字符编码仅需要几位,而有的则需要十几位,这就导致了如果都采用固定长度的编码时,就会造成空间的浪费。所以就衍生出了对于Unicode编码的不同实现方式,如常见到的UTF-8UTF-16UTF-32,其中UTF-8是最为常用的编码方式,它采用了变长字节的表示方式,即使用的字节数是可变的,这个变化是根据字符对应的Unicode编号的大小所变化的,即编号小的字符使用的字节数就少,编号大的字符使用的字节数就多,因此,使用的字节个数从1到4个不等。

所以,回到主题,Python中用到的字符串前面加上u的作用是声明对后面的字符串进行unicode编码,常用于中文字符串的处理。Unicode是书写国际文本的标准方法,如果你想用你的母语来写文本的时候,就需要一个支持Unicode的编译器,Python允许处理Unicode文本,只需在字符串前加上前缀u即可。一般英文的字符串不需要进行任何编码的处理,但是当你使用中文的时候,就需要在前面加上u了。

 

最后再引用知乎上某个大佬举的例子来加深理解一下:https://www.zhihu.com/question/23374078/answer/65352538

 

举一个例子:It's 知乎日报

你看到的unicode字符集是这样的编码表:

I 0049
t 0074
' 0027
s 0073
  0020
知 77e5
乎 4e4e
日 65e5
报 62a5

每一个字符对应一个十六进制数字。

计算机只懂二进制,因此,严格按照unicode的方式(UCS-2),应该这样存储:

I 00000000 01001001
t 00000000 01110100
' 00000000 00100111
s 00000000 01110011
  00000000 00100000
知 01110111 11100101
乎 01001110 01001110
日 01100101 11100101
报 01100010 10100101

这个字符串总共占用了18个字节,但是对比中英文的二进制码,可以发现,英文前9位都是0!浪费啊,浪费硬盘,浪费流量。

怎么办?

UTF。

UTF-8是这样做的:

1. 单字节的字符,字节的第一位设为0,对于英语文本,UTF-8码只占用一个字节,和ASCII码完全相同;

2. n个字节的字符(n>1),第一个字节的前n位设为1,第n+1位设为0,后面字节的前两位都设为10,这n个字节的其余空位填充该字符unicode码,高位用0补足。

这样就形成了如下的UTF-8标记位:

0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
... ...

于是,”It's 知乎日报“就变成了:

I 01001001
t 01110100
' 00100111
s 01110011
  00100000
知 11100111 10011111 10100101
乎 11100100 10111001 10001110
日 11100110 10010111 10100101
报 11100110 10001010 10100101

和上边的方案对比一下,英文短了,每个中文字符却多用了一个字节。但是整个字符串只用了17个字节,比上边的18个短了一点点。

另外一个汉字在UTF-8编码的情况下可能需要三个字节,而使用gbk两个字节就足够了,所以有时候为了节省流量和硬盘,在使用中文的时候,也有用gbk或者gbk2312编码的。

 

 

 

 

 

 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值