一文带你了解Python中的字符串是什么


Posted in Python onNovember 20, 2018

在《 详解Python拼接字符串的七种方式 》这篇文章里,我提到过,字符串是程序员离不开的事情。后来,我看到了一个英文版本的说法:

There are few guarantees in life: death, taxes, and programmers needing to deal with strings.
它竟然把程序员处理字符串跟死亡大事并列了,可见这是多么命中注定……

回头看其它文章,我发现这种说法得到了佐证,因为我在无意中已零零碎碎地提及了字符串的很多方面,例如:字符串读写文件、字符串打印、字符串不可变性、字符串Intern机制、字符串拼接、 是否会取消字符串 ,等等。而这些,还只能算字符串面目的冰山一角。

既然如此,那干脆再单独写写Python的字符串吧。这篇内容可能会很基(li)础(lun),并不是什么“骚操作”或“冷知识”,权当是一份温故而求知新的笔记。

1 Python字符串是什么?

根据维基百科定义:字符串是由零个或多个字符组成的有限序列。而在Python 3中,它有着更明确的意思: 字符串是由Unicode码点组成的不可变序列 (Strings are immutable sequences of Unicode code points.)

字符串是一种序列,这意味着它具备序列类型都支持的操作:

# 以下的s、t皆表示序列,x表示元素
x in s # 若s包含x,返回True,否则返回False
x not in s # 若s包含x,返回False,否则返回True
s + t # 连接两个序列
s * n # s复制n次
s[i] # s的索引第i项
s[i:j] # s切片从第i项到第j-1项
s[i:j:k] # s切片从第i项到第j-1项,间隔为k
len(s) # s的长度
min(s) # s的最小元素
max(s) # s的最大元素
s.index(x) # x的索引位置
s.count(x) # s中出现x的总次数

字符串序列还具备一些特有的操作,限于篇幅,按下不表。预告一下,下一篇《 你真的知道Python的字符串怎么用吗? 》将会展开介绍,敬请期待……

字符串序列是一种不可变序列,这意味着它不能像可变序列一样,进行就地修改。例如,在字符串“Python”的基础上拼接“Cat”,得到字符串“PythonCat”,新的字符串是一个独立的存在,它与基础字符串“Python”并没有关联关系。

basename = "Python"
myname = basename + "Cat"
id(basename) == id(myname) >>> False
# 作为对比,列表能就地修改
baselist = ["Python"]
baselist.append("Cat")
print(baselist) >>> ['Python', 'Cat']

字符串这种序列与其它序列(如列表、元组)的不同之处在于,它的“元素”限定了只能是Unicode码点。Unicode码点是什么呢?简单理解,就是用Unicode编码的字符。那字符是什么呢? 字符 是人类书写系统的各类符号,例如阿拉伯数字、拉丁字母、中文、日文、藏文、标点符号、控制符号(换行符、制表符等)、其它特殊符号(@#¥%$*等等)。那Unicode编码又是什么呢?Unicode别名是万国码、国际码,它是一种适用性最广的、将书写字符编码为计算机数字的标准。

总所周知,在最底层的计算机硬件世界里,只有0和1。那么,怎么用这个二进制数字,来表示人类的文化性的字符呢?这些字符数量庞大,而且还在日益增长与变化,什么样的编码方案才是最靠谱的呢?

历史上,人类创造了多种多样的字符编码标准,例如ASCII(1963年)编码,以西欧语言的字符为主,它的缺点是只能编码128个字符;例如GB2312(1981年),这是中国推出的编码标准,在兼容ASCII标准的基础上,还加入了对日文、俄文等字符的编码,但缺点仍是编码范围有限,无法表示古汉语、繁体字及更多书写系统的字符。

Unicode编码标准于1991年推出,至今迭代到了第11版,已经能够编码146个书写系统的130000个字符,可谓是无所不包,真不愧是“国际码”。Unicode编码其实是一个二进制字符集,它建立了从书写字符映射成唯一的数字字符的关系,但是,由于各系统平台对字符的理解差异,以及出于节省空间的考虑,Unicode编码还需要再做一次转换,转换后的新的二进制数字才能作为 实际存储及网络传输时的编码 。

这种转换方式被称为 Unicode转换格式 (Unicode Transformation Format,简称为UTF),它又细分为UTF-8、UTF-16、UTF-32等等方式。我们最常用的是UTF-8。为什么UTF-8最常用呢?因为它是可变长度的编码方案,针对不同的字符使用不同的字节数来编码,例如编码英文字母时,只需要一个字节(8个比特),而编码较复杂的汉字时,就会用到三个字节(24个比特)。

一文带你了解Python中的字符串是什么

二进制的编码串可以说是给机器阅读的,为了方便,我们通常会将其转化为十六进制,例如“中”字的Unicode编码可以表示成 0x4e2d ,其UTF-8编码可以表示为 0xe4b8ad ,'0x'用于开头表示十六进制,这样就简洁多了。不过,UTF-8编码的结果会被表示成以字节为单位的形式,例如“中”字用UTF-8编码后的字节形式是 \xe4\xb8\xad 。

Python中为了区分Unicode编码与字节码,分别在开头加“u”和“b”以示区分。在Python 3中,因为Unicode成了默认编码格式,所以“u”被省略掉了。

# 字符转Unicode编码
# Python3中,开头的u被省略,b不可省略
hex(ord('中')) >>> '0x4e2d'
hex(ord('A')) >>> '0x41'
# 字符转UTF-8编码(encode)
'中'.encode('utf-8') >>> b'\xe4\xb8\xad'
'A'.encode('utf-8') >>> b'A'
# Unicode编码还原成字符
chr(0x4e2d) >>> '中'
chr(0x41) >>> 'A'
# UTF-8编码还原成字符(decode)
b'\xe4\xb8\xad'.decode('utf-8') >>> '中'
b'A'.decode('utf-8') >>> 'A'

总结一下,Python 3 中的字符串是由Unicode码点组成的不可变序列,也即是,由采用Unicode标准编码的字符组成的不可变序列。Unicode编码将书写系统的字符映射成了计算机二进制数字,为了方便,通常显示为十六进制;在运算内存中,字符以Unicode编码呈现,当写入磁盘或用于网络传输时,一般采用UTF-8方式编码。

在Python 2中,因为历史包袱,即Python先于Unicode编码而诞生,所以其编码问题是个大难题。幸好抛弃Python 2已成大势所趋,所以我就不再对此做介绍或比对了。

2 Python字符串 VS Java字符串

虽然不提纵向版本间的差异,但是,我想将Python字符串与其它编程语言做一个横向对比。我觉得这会是挺好玩的事。通过跨语言的比较,也许我们能加深对一个事物(字符串)的理解,还可能受到启发,得到对“编程语言”及“编程哲学”的领悟。

由于本人才疏学浅,本文就只对两点皮毛特性作说明,欢迎读者斧正和补充。

(1)字符串的定义方式

Python的字符串是内置类型,所以使用起来很方便,有如下三种定义方式:

str_0 = '''Python字符串可以写在用三引号对内,表示多行字符串。
还可以写在单引号对内,
当然还可以写在双引号对内。
'''
str_1 = 'Python猫是一只猫'
str_2 = "Python猫是一个微信公众号"

Java的字符串不是内置类型,它属于对象,需要通过String类来创建。不过,正因为字符串太常用,所以Java特意预定义了一个字符串类String,使得程序员也可以像这样来定义: String name = "Python猫"; ,而不必这样写: String name = new String("Python猫"); 。

Java的字符串只能写在双引号内,不具备Python中单双引号混用的灵活。至于三引号的多行字符串表示法,Java程序员表示羡慕得要死,那种痛苦,受过折磨的人最懂。写出来让Python程序员开心一下:

String s = "Java 的多行字符串很麻烦,\n"
  + "既要使用换行符,\n"
  + "还需要使用加号拼接";

为什么Java不支持多行字符串、什么时候支持多行字符串?此类问题在Python程序员眼里,可能很费解,但它绝对能排进“Java程序员最希望能实现的特性”的前列。好不容易,官方有计划在Java 11 实现,但今年9月发布的Java 11 仍是没有,现在改计划到Java 12 了。

(2)单个字符与字符序列

Java中其实也有单引号的使用,用在char类型上,例如 char c = 'A'; 。char是一种内置类型,表示单个用Unicode编码的字符。Python中没有char类型,字符串类型通吃一切。

前面说到,Python的字符串是一种字符序列,而Java的字符串并不是一种序列,要表示相近的概念的话,就得用到 字符数组 或者 字符串数组 ,例如:

char[] a = { 'a', 'b', 'c'}; 
String[] str = new String[]{"1","2","3"};

字符数组和字符串数组是一种序列,但并不是字符串,它们之间如果要相互转换,还是挺麻烦的。另外,说是序列,但Java的序列操作绝对无法跟Python相比,别的不说,就上面提及的几个基础操作,试问Java能否实现、实现起来要花费多大力气?

最后来个Ending,关于“Python字符串到底是什么”就说到这啦,希望对你有所帮助。下次,我再跟大家说说“Python字符串到底怎么用”,敬请期待。希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
利用Python的Django框架中的ORM建立查询API
Apr 20 Python
深入源码解析Python中的对象与类型
Dec 11 Python
详解python中Numpy的属性与创建矩阵
Sep 10 Python
关于python多重赋值的小问题
Apr 17 Python
pyqt 多窗口之间的相互调用方法
Jun 19 Python
在python里面运用多继承方法详解
Jul 01 Python
Pandas DataFrame中的tuple元素遍历的实现
Oct 23 Python
python TK库简单应用(实时显示子进程输出)
Oct 29 Python
Python tkinter和exe打包的方法
Feb 05 Python
django 利用Q对象与F对象进行查询的实现
May 15 Python
用Python仅20行代码编写一个简单的端口扫描器
Apr 08 Python
python如何读取和存储dict()与.json格式文件
Jun 25 Python
pygame游戏之旅 创建游戏窗口界面
Nov 20 #Python
pygame游戏之旅 python和pygame安装教程
Nov 20 #Python
python2和python3的输入和输出区别介绍
Nov 20 #Python
python使用pygame框架实现推箱子游戏
Nov 20 #Python
浅析python的优势和不足之处
Nov 20 #Python
opencv实现图片模糊和锐化操作
Nov 19 #Python
python实现朴素贝叶斯算法
Nov 19 #Python
You might like
PHP 和 MySQL 开发的 8 个技巧
2006/10/09 PHP
php获取远程图片体积大小的实例
2013/11/12 PHP
10个超级有用的PHP代码片段果断收藏
2015/09/23 PHP
PHP数据库操作Helper类完整实例
2016/05/11 PHP
兼容ie和firefox js关闭代码
2008/12/11 Javascript
在JQuery dialog里的服务器控件 事件失效问题
2010/12/08 Javascript
收集的10个免费的jQuery相册
2011/02/26 Javascript
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
2013/02/05 Javascript
Js 代码中,ajax请求地址后加随机数防止浏览器缓存的原因
2013/05/07 Javascript
浅析javascript中的事件代理
2015/11/06 Javascript
jquery+css实现动感的图片切换效果
2015/11/25 Javascript
node.js实现博客小爬虫的实例代码
2016/10/08 Javascript
AngularJS解决ng界面长表达式(ui-set)的方法分析
2016/11/07 Javascript
使用JavaScript获取URL中的参数(两种方法)
2016/11/16 Javascript
Vue计算属性的使用
2017/08/04 Javascript
JavaScript中使用import 和require打包后实现原理分析
2018/03/07 Javascript
Angularjs实现控制器之间通信方式实例总结
2018/03/27 Javascript
js动态引入的四种方法
2018/05/05 Javascript
在vue项目中引入高德地图及其UI组件的方法
2018/09/04 Javascript
简单了解vue中的v-if和v-show的区别
2019/10/08 Javascript
JS运算符优先级与表达式示例详解
2020/09/04 Javascript
教你用Python写安卓游戏外挂
2018/01/11 Python
Sanic框架异常处理与中间件操作实例分析
2018/07/16 Python
Python 线性回归分析以及评价指标详解
2020/04/02 Python
如何使用Cython对python代码进行加密
2020/07/08 Python
Python selenium实现断言3种方法解析
2020/09/08 Python
python用分数表示矩阵的方法实例
2021/01/11 Python
英国优质鞋类专家:Robinson’s Shoes
2017/12/08 全球购物
遇到的Mysql的面试题
2014/06/29 面试题
关于逃课的检讨书
2014/01/23 职场文书
2014年驻村干部工作总结
2014/11/17 职场文书
教学督导岗位职责
2015/04/10 职场文书
员工辞退通知书
2015/04/17 职场文书
2015年环卫工作总结
2015/04/28 职场文书
2015年禁毒工作总结
2015/04/30 职场文书
刑事法律意见书
2015/06/04 职场文书