在这条推文《详解Python拼接字符串的七种方式》中,我提到了字符串是程序员离不开的东西。后来看到英文版的说法:Therewereguaranteesinlife:death,taxes,andprogrammersneedtodealwithstrings。居然把程序员对字符串的处理和死亡并列,可见命中注定。。。回头看其他文章,发现这个说法得到了佐证,因为我在点点滴滴不经意间提到了字符串的很多方面,比如如:字符串读写文件、字符串打印、字符串不可变性、字符串Intern机制、字符串拼接、是否取消字符串等。而这些只能算是字符串的冰山一角。既然如此,那我们就单独写Python字符串吧。这个内容可能是很基础(li)基础(lun)的,不是什么“骚操作”或者“冷知识”,应该是一个温故知新的笔记。1什么是Python字符串?根据维基百科的定义:字符串是由零个或多个字符组成的有限序列。在Python3中,它有更明确的含义:字符串是Unicode代码点的不可变序列。字符串是Unicode代码点的不可变序列。字符串是一个序列,也就是说它具有序列类型所有支持的操作:#下面的s和t都代表序列,x代表s中的元素x#如果s中包含x,则返回True,否则返回Falsexnotins#如果s包含x,返回False,否则返回Trues+t#连接两个序列s*n#s复制n次s[i]#s索引i项s[i:j]#s从i项到j-1items[i:j:k]#s从itemi到itemj-1的切片,区间为klen(s)#s的长度min(s)#s的最小元素max(s)#的最大元素ss.index(x)#x的索引位置s.count(x)#x在s中出现的总次数字符串序列还有一些独特的操作,限于篇幅就不一一列举了。作为预告,下一篇《你真的知道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别名是UniversalCode和InternationalCode,是应用最广泛的将书面字符编码成计算机数字的标准。众所周知,在计算机硬件最低的世界里,只有0和1。那么,如何用这个二进制数来表示人类的文化字符呢?这些人物的数量是巨大的,而且还在不断的增长和变化。什么样的编码方案最可靠?历史上,人类创造了多种字符编码标准,如ASCII(1963)编码,主要是西欧语言字符。它的缺点是只能编码128个字符;例如GB2312(1981),它是中国引入的编码标准,在兼容ASCII标准的基础上,还增加了日文、俄文等字符的编码,但缺点仍然是编码范围是有限,不能表示古文、繁体字等文字。Unicode编码标准于1991年推出,至今已迭代至第11版。它已经能够编码146种书写系统中的130,000个字符。Unicode编码实际上是一种二进制字符集,它建立了从书面字符到唯一数字字符的关系。但是由于各个系统平台对字符理解的差异,以及出于节省空间的考虑,Unicode编码还是需要重新做一遍。经过一次转换后,转换后的新二进制数可以作为实际存储和网络传输的编码。这种转换方式称为统一码转换格式(UnicodeTransformationFormat,简称UTF),又细分为UTF-8、UTF-16、UTF-32等。我们最常使用的是UTF-8。为什么UTF-8最常用?因为它是一种变长编码方案,所以它使用不同的字节数来对不同的字符进行编码。例如,在对英文字母进行编码时,只需要一个字节(8位),而对较复杂的汉字进行编码时,则会使用三个字节(24位)。二进制代码串可以说是被机器读取的。为了方便,我们通常将其转换成十六进制。例如“中”的Unicode编码可以表示为0x4e2d,它的UTF-8编码可以表示为0xe4b8ad。开头用'0x'表示十六进制,简洁多了。但是UTF-8编码的结果会以字节来表示。例如“中”用UTF-8编码的字节形式是\xe4\xb8\xad。Python中为了区分Unicode编码和字节码,在开头加上“u”和“b”来区分。在Python3中,由于Unicode成为默认编码格式,因此省略了“u”。#字符转Unicode编码#Python3中省略了开头的u,b不能省略hex(ord('中'))>>>'0x4e2d'hex(ord('A'))>>>'0x41'#字符转换为UTF-8编码(encode)'in'.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')>>>'in'b'A'.decode('utf-8')>>>'A'总之,Python3中的字符串是不可变序列Unicodecodepoints,即以Unicode标准编码的不可变字符序列。Unicode编码将书写系统的字符映射为计算机二进制数。为了方便,通常显示为十六进制;在计算内存中,字符以Unicode编码呈现。在写入磁盘或进行网络传输时,UTF一般采用-8方式编码。在Python2中,因为历史包袱,也就是Python诞生于Unicode编码之前,所以它的编码问题是个大问题。庆幸的是,放弃Python2已经成为大势所趋,我就不再介绍和比较了。2PythonstringVSJavastring虽然没有提到垂直版本之间的区别,但我想对Pythonstring和其他编程语言做一个横向比较。我认为这会很有趣。通过跨语言的比较,我们或许可以加深对一个事物(字符串)的理解,也可能会受到启发,对“编程语言”和“编程哲学”有所了解。由于本人孤陋寡闻,本文只对皮草的两个特点进行说明。欢迎读者指正和补充。(1)如何定义字符串Python字符串是一种内置类型,使用起来非常方便。有如下三种定义方式:str_0='''Python字符串可以写在三引号内表示多行字符串。也可以写成单引号,当然也可以写成双引号。'''str_1='Python猫是猫'str_2="Python猫是微信"Java的string不是内置类型,是对象,需要通过String类创建。但是,由于字符串是如此常用,Java特意预定义了一个字符串类String,让程序员也可以这样定义:Stringname="Pythoncat";而不是写:Stringname=newString("Pythoncat");.Java字符串只能写在双引号内,不具备Python中单双引号混用的灵活性。对于三重引号的多行字符串表示,Java程序员表示羡慕死了。受过折磨的人最了解那种痛苦。写出来让Python程序员开心:Strings="Java的多行字符串很麻烦,\n"+"需要用换行符,\n"+"还需要用加号拼接";为什么Java不支持多行字符串,什么时候支持多行字符串?这种问题在Python程序员眼里可能很难理解,但绝对可以排在“Java程序员最希望实现的特性”的前列。毕竟官方的计划是在Java11中实现,但是今年9月发布的Java11还是没有。现在计划改为Java12。(2)单个字符和字符序列其实Java中也有单引号的使用,是用在char类型上的,比如charc='A';.char是表示单个Unicode编码字符的内置类型。Python中没有char类型,string类型通吃。如前所述,Python字符串是字符序列,但Java字符串不是序列。要表达类似的概念,必须使用字符数组或字符串数??组,例如:char[]a={'a','b','c'};String[]str=newString[]{"1","2","3"};字符数组和字符串数组都是序列,但不是字符串,相互之间转换还是挺麻烦的。另外,说是序列,但是Java的序列操作和Python是绝对没法比的。别的不说,就上面提到的基本操作来说,Java能不能实现,实现起来需要付出多大的努力?最后,这是Ending,就是关于“什么是Python字符串”的全部内容,希望对你有所帮助。下一次,我会告诉你“如何使用Python字符串”,敬请期待。本文首发于微信公众号【Python猫】,后台回复“爱学习”,送20+精选电子书。延伸阅读:https://zh.wikipedia.org/wiki...https://zh.wikipedia.org/wiki...https://dwz.cn/AvWg1EDxhttps://yiyibooks.cn/xx/pytho…https://github.com/acmerfight…
