字符串
所谓字符串,就是由零个或多个字符组成的有限序列。
如果我们把单个或多个字符用单引号或者双引号包围起来,就可以表示一个字符串。字符串中的字符可以是各种字符各种特殊字符与各种语言的文字,emoji字符等各种字符。
字符串最简单的定义就是单引号或者双引号括起来即可,除此之外三个双引号或单引号开头的字符串可以折行。(没错和多行注释是一样的,前面有变量赋值语句就是字符串,不然就是注释,为了区分,一般建议写这种字符串时使用单引号,注释使用双引号)
转义字符与原始字符
可以在字符串中使用\
(反斜杠)来表示转义,也就是说\
后面的字符不再是它原来的意义,例如:\n
不是代表反斜杠和字符n
,而是表示换行;\t
也不是代表反斜杠和字符t
,而是表示制表符。所以如果字符串本身又包含了'
、"
、\
这些特殊的字符,必须要通过\
进行转义处理。
在\
后面还可以跟一个八进制或者十六进制数来表示字符,例如\141
和\x61
都代表小写字母a
,前者是八进制的表示法,后者是十六进制的表示法。另外一种表示字符的方式是在 \u`后面跟Unicode字符编码(一般用utf-8)。
以r
或R
开头,这种字符串被称为原始字符串,意思是字符串中的每个字符都是它本来的含义,没有所谓的转义字符。类似于之前我们学输出时学的前面加f的格式化字符输出,定义字符时也可以使用格式化字符。
# 头尾带单引号的hello, world!
s1 = '\'hello, world!\''
print(s1)
# 头尾带反斜杠的hello, world!
s2 = '\\hello, world!\\'
print(s2)
# 字符串s1中\t是制表符,\n是换行符
s1 = '\time up \now'
print(s1)
# 字符串s2中没有转义字符,每个字符都是原始含义
s2 = r'\time up \now'
print(s2)
s3 = f'{s2} '
s1 = '\141\142\143\x61\x62\x63'
s2 = '\u5b57\u7b26
print(s1, s2)
这些结果都很简单,各位可以自行观察。
字符串的运算
字符串的拼接与重复
字符串有许多和列表列表类似的东西,也支持使用+ 进行字符串的拼接,* 进行字符串的重复。如下例示
s1 = 'hello' + ' ' + 'world'
print(s1) # hello world
s2 = '!' * 3
print(s2) # !!!
s1 += s2
print(s1) # hello world!!!
字符串的比较运算
两个字符串类型的变量,可以直接使用比较运算符比较两个字符串的相等性或大小。需要说明的是,因为字符串在计算机内存中也是以二进制形式存在的,那么字符串的大小比较比的是每个字符对应的编码的大小。主要知道大写英文字符小于小写英文字符,按字母表顺序越后面的越大就可以了,其他的不用特意知道,需要的时候查一下就可以了。编码可以使用ord()函数获得,chr()可以再把编码返回字符。
python中还有is
运算符(身份运算符)可以用于比较字符串,如果用is
来比较两个字符串,它比较的是两个变量对应的字符串是否在内存中相同的位置(内存地址),简单的说就是两个变量是否对应内存中的同一个字符串。
字符串的成员运算
用in
和not in
判断一个字符串中是否存在另外一个字符或字符串,in
和not in
运算通常称为成员运算,会产生布尔值True
或False
如下例示
s1 = 'hello, world'
print('llo' in s1) # True
s2 = 'goodbye'
print(s2 in s1) # False
字符串的索引、切片与遍历
字符串的索引切片与遍历和列表元组的没什么区别,你可以把每个字符看成一个元素,把字符串当成一种元组,索引切片操作都没什么不同,遍历也一样,enumerate也一样可以用。
字符串也是不可变类型,不能使用索引对单个字符进行赋值等操作。
其他
还可以使用str()将许多数值类型直接转成字符串,整数浮点数什么的不用说,列表什么的其实也可以不过没什么用罢了。
可以使用len() 获取字符串长度。
join()可以把多个字符拼接成一个字符
字符串的方法
字符串的大小写转换
主要是四个函数,capitatize() title() upper() lower() 如下例示
s1 = 'hello, world!'
# 使用capitalize方法获得字符串首字母大写后的字符串
print(s1.capitalize()) # Hello, world!
# 使用title方法获得字符串每个单词首字母大写后的字符串
print(s1.title()) # Hello, World!
# 使用upper方法获得字符串大写后的字符串
print(s1.upper()) # HELLO, WORLD!
s2 = 'HAPPY'
# 使用lower方法获得字符串小写后的字符串
print(s2.lower()) # happy
字符串查找与替换
查找
find()与index()函数都可以在 字符串中查找有没有指定字符串,他们找到了都会返回两个字符串重合的首字符的索引,不同的是,find如果找不到会返回-1,而index如果找不到会直接报错。和在列表时一样,也可以指定寻找的起始与终止位置。
还可以使用rfind() rindex()从右往左寻找。
查找没什么好说的,和列表什么的都一样,下面重点说说替换。
替换
一般使用replace()函数,字符串是不可变类型,所有这种改变字符串值的命令都只会返回更改后的副本,需要赋值才能改变该字符串。如下例示
a = 'happy everyday'
a = a.replace('ha', '') # ppy everyday
print(a)
a = a.replace('ppy', 'happy') # happy everyday
print(a)
a = a.replace('day', 'one') # happy everyone
print(a)
b = a.replace('y', '')
c = a.replace('y', '', 1) # happ everone happ everyone
print(b, c)
replace有三个参数,前两个必须填写,第一个是要被替换的字符串,第二个是要替换成的字符串,最后一个参数可选,参数是几就表示只替换前几次。
修剪
strip()方法可以帮我们获得将原字符串修剪掉左右两端空格之外的字符串,这个功能非常实用,很多数据为了格式化输出在关键数据两端常有一些空格或者搭配一些填充字符,strip可以很方便的去掉他们。除了strip还有lstrip()和rstrip(),很明显这两个就是只删左边或右边的版本。
s = ' 123456789@000.com \t'
print(s.strip(), s.lstrip(), s.rstrip(),sep='|')
# 123456789@000.com|123456789@000.com | 123456789@000.com
字符串的拆分与合并
拆分
使用split()函数方法,默认使用空格拆分,也可以在括号内指定拆分字符,还可以使用maxsplit参数确定最大拆分次数,如下例示
s1 = 'you love me , i love you , that so sweet'
s2 = s1.replace(',', '')
ss = s2.split()
print(ss) # ['you', 'love', 'me', 'i', 'love', 'you', 'that', 'so', 'sweet']
for s in ss:
print(s, end=' ') # you love me i love you that so sweet
合并
使用join方法可以合并多个字符串,并可以设定间隔。如下例示
# 接着上面的代码
print()
s3=','.join(ss)
print(s3) # you,love,me,i,love,you,that,so,sweet
字符串的性质判断
startswith
、endswith
来判断字符串是否以某个字符串开头和结尾;还可以用is
开头的方法判断字符串的特征,这些方法都返回布尔值,如下例示
s1 = 'hello, world!'
# startwith方法检查字符串是否以指定的字符串开头返回布尔值
print(s1.startswith('el')) # False
print(s1.startswith('he')) # True
# endswith方法检查字符串是否以指定的字符串结尾返回布尔值
print(s1.endswith('d!')) # True
s2 = 'abc123456'
# isdigit方法检查字符串是否由数字构成返回布尔值
print(s2.isdigit()) # False
# isalpha方法检查字符串是否以字母构成返回布尔值
print(s2.isalpha()) # False
# isalnum方法检查字符串是否以数字和字母构成返回布尔值
print(s2.isalnum()) # True
字符串的格式化
可以用center
、ljust
、rjust
方法做居中、左对齐和右对齐的处理,当然还可以使用之前输出时使用的格式化方法也可以对字符串进行格式化。如下例示
s1 = 'hello, world'
# center方法以宽度20将字符串居中并在两侧填充*
print(s1.center(20, '*')) # ****hello, world****
# rjust方法以宽度20将字符串右对齐并在左侧填充空格
print(s1.rjust(20)) # hello, world
# ljust方法以宽度20将字符串左对齐并在右侧填充~
print(s1.ljust(20, '~')) # hello, world~~~~~~~~
print(f'{s1:-<20s}') # hello, world--------
# 用0填充
print(s1.zfill(20)) # 00000000hello, world
字符的编码与解码
使用encode()与decode(),默认使用utf-8(万国码的一种实现方式),也可以自己指定编码与解码方式,比如说‘gbk’也就是国标扩,gbk中写中文是两个字节,而万国码要使用三个字节。
编码与解码必须使用同一种方式,如果不同有可能会报错,或者出现乱码。
有些编码不能编译一些字符,比如说中文不能用‘iso-8859-1’(latin-1)编码,否则会产生编码黑洞(所有字符变成?号,不能还原)(pycharm会直接报错阻止这种编码)
一般来说utf-8是我们编码时的最佳选择,utf-8是一种变长编码,编码英文数字时只要一个字节,编码中文是3个字节,编码emoji表情时要四个字节,也有占两个字节的内容。
a = '爱祖国爱人民'
b = a.encode('gbk')
print(type(b)) # <class 'bytes'>
print(b, len(b)) # b'\xb0\xae\xd7\xe6\xb9\xfa\xb0\xae\xc8\xcb\xc3\xf1' 12
c = b'\xb0\xae\xd7\xe6\xb9\xfa\xb0\xae\xc8\xcb\xc3\xf1'
print(c.decode('gbk')) # 爱祖国爱人民
a = '爱祖国爱人民😀'
b = a.encode()
print(type(b))
print(b, len(b))
c = b'\xe7\x88\xb1\xe7\xa5\x96\xe5\x9b\xbd\xe7\x88\xb1\xe4\xba\xba\xe6\xb0\x91\xf0\x9f\x98\x80'
print(c.decode()) # 爱祖国爱人民😀
百分号编码与base64编码
百分号编码主又称:URL编码(URL encoding)是特定上下⽂的统⼀资源定位符(URL)的编码机制,实际上也适用于统⼀资源标志符(URI)的编码。也用于为 application/x-www-form-urlencoded MIME准备数据,因为它用于通过HTTP的请求操作(request)提交HTML表单数据。最常见的也就是网址书写,一些保留字需要使用百分号编码进行替换,具体见下图
如果想表示百分号自身使用%25,百分号编码不建议使用在除了在url书写这些字符的其他地方。
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 - _ . ~ 这些是未保留字,即是无需编码的字符,也不建议编码
百分号编码的原理是把字符的ASCII码用两位的16进制表示后前面加上转义字符’%'就是百分号编码了,对于非ASCII字符, 需要转换为UTF-8字节序,然后每个字节按照上述⽅式表示。
base64编码是⼀种基于64个可打印字符来表示⼆进制数据的表示⽅法。由于 ,所以每6个比特为⼀个单元,对应某个可打印字符。3个字节相当于24个比特,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中⽽不同。
Base64常用于在通常处理⽂本数据的场合,表示、传输、存储⼀些⼆进制数据,包括MIME的电⼦邮件及XML的⼀些复杂数据。
在我个人看来base64编码更像是一种密码
原理就是把一段话首先分成每三个字符一组,不足的用0字节值补上,然后把每三个字符的ASCII码写成八位数的二进制数字,然后把这二十四位的二进制数字按顺序重新分成4份,得到四个六位数的二进制数字,根据所得数字转成十进制对应的索引再替换成字符,最后之前补了几个字符空缺就再加上几个‘=’号
索引表如下
字符串加密解密
对称加密
对称加密就是加密和解密是用同一个密钥,也就是会加密也就明白解密的方法,这种加密方式就称为对称加密。
这是比较 容易想到的加密方式,最早是一种叫凯撒的密码,python中可以进行类似的实现,如下例示
message = 'attack at dawn'
table = str.maketrans('abcdefghijklmnopqrstuvwxyz', 'fghijklmnopqrstuvwxyzabcde')
print(table)
result=message.translate(table)
print(result)
使用maketrans()函数可以生成这种一一对照的密码对照表,然后使用translate()函数进行加密即可,这是最简单的一种密码,我们也就简单介绍下这种简单的例子就可以了,感兴趣的同学可以自行去了解更深层次的内容。
非对称加密
非对称加密则是有公钥与私钥之分,会用公钥加密不代表知道私钥,没有私钥便不能解密,好处当然就是更加安全了,不过缺点自然就是效率低,解密比对称加密慢很多。
tips:非对称加密非常复杂,最简单的例子也不怎么简单,在此就不展开了,有兴趣了解的自行去网上搜索即可。
小结
字符串是非常重要的一种数据类型,熟悉对它的操作也是非常重要,因为我们对文本信息的处理是非常常用的。
正则表达式也是字符串非常重要的一部分,不过这个题目很大,在此就不展开了,基础操作知道以上的知识已经足够了。