字符串 今天跟大家来说一说Python中的字符串数据结构。
让我们回顾一下可变类型及不可变类型:
str
、int
、tuple
dict
、list
今天讲解的字符串属于不可变类型。
Python3中的字符串是Unicode的序列,也就是说,Python3的字符串支持多语言了;Python2中的字符串是byte序列。
例如:
In[1]: print('含有中文的字符串str')
含有中文的字符串str
对于单个字符的编码,Python提供了ord()
内置函数来获取字符的整数表示;chr()
内置函数则把编码转换为对应的字符。例如:
In[2]: ord('A')
Out[2]: 65
In[3]: ord('中')
Out[3]: 20013
In[4]: chr(97)
Out[4]: 'a'
In[5]: chr(25991)
Out[5]: '文'
如果要知道字符的整数编码,那么还可以用其十六进制的形式这么写:
In[6]: '\u4e2d\u6587'
Out[6]: '中文'
Python的字符编码就介绍到这里。接下来介绍Python字符串的常用方法,看看字符串在日常当中是怎么用的。
字符串常用方法:
join
split
、rsplit
、splitlines
、partition
、rpartition
capitalize
、title
、lower
、upper
、swapcase
center
、ljust
、rjust
、zfill
、strip
、rstrip
、lstrip
count
、find
、rfind
、index
、rindex
、replace
join允许我们使用特定的字符来连接字符串。直接看例子吧:
In[7]: lst = ['i', 'am', 'lavenliu']
In[8]: ' '.join(lst)
Out[8]: 'i am lavenliu'
join是字符串方法,参数是内容为字符串的可迭代对象,接收者(在这里为空格)作为连接符。使用逗号进行连接:
In[9]: ','.join(lst)
Out[9]: 'i,am,lavenliu'
除了join外,我们还可以使用+
进行两个字符串的连接:
In[10]: 'my' + ' name'
Out[10]: 'my name'
# split
>>> s = 'my name is lavenliu'
>>> s
'my name is lavenliu'
>>> s.split()
['my', 'name', 'is', 'lavenliu']
>>> s.split(maxsplit=1) # maxsplit参数表示分割多少次;默认值为-1,表示分割所有分隔符
>>> s.split('ls')
['my name is lavenliu']
>>> s.split('is')
['my name ', ' lavenliu']
>>> s.split(' ', 1)
['my', 'name is lavenliu']
s.split('is') # 以“is”为分隔符
s.split(' ', 1) # 以空格为分隔符,从左到右分隔一次
s.split(' ', 2) # 以空格为分隔符,从左到右分隔两次
s.split(' ', -1) # -1就是默认值,直到字符串分隔完成
['my', 'name', 'is', 'lavenliu']
# rsplit方法
s.rsplit()
['my', 'name', 'is', 'lavenliu']
s.rsplit(' ')
['my', 'name', 'is', 'lavenliu']
s.rsplit(' ', 1) # 与s.split(' ', 1)的分隔形式相反
['my name is', 'lavenliu']
我们看一看split函数的原型该怎么写:
def split(s, sep, maxsplit):
ret = []
tmp = []
i = 0
for c in s:
if c != sep:
tmp.append(c)
else:
i += 1
ret.append(''.join(tmp))
tmp.clear()
if maxsplit > 0 and i >= maxsplit:
return ret
return ret
rsplit方法的原型为:
def rsplit(s, sep, maxsplit):
ret = []
tmp = []
for c in reversed(s):
if c != sep:
tmp.append(c)
else:
i += 1
ret.append(''.join(reversed(tmp)))
tmp.clear()
if maxsplit > 0 and i >= maxsplit:
ret.append()
return reversed(ret)
return reversed(ret)
splitlines方法:
In[12]: s = '''i am lavenliu
...: i love python'''
In[13]: print(s.splitlines()) # 按行分割,并且返回结果不带换行符
['i am lavenliu', 'i love python']
In[14]: print(s.splitlines(True)) # 按行分割,并且返回结果带换行符
['i am lavenliu\n', 'i love python']
partition方法:
In[15]: s = 'i am lavenliu'
In[16]: s.partition(' ')
Out[16]: ('i', ' ', 'am lavenliu')
partition总是返回一个三元组,它按传入的分隔符分割一次,得到head,tail,返回结果是head,sep,tail。rpartition是partition从右往左的版本。再看一个partition的例子,
In[17]: cfg = 'mysql.connect = mysql://user:password@127.0.0.1:3306/test'
In[18]: print(cfg.partition('='))
('mysql.connect ', '=', ' mysql://user:password@127.0.0.1:3306/test')
In[19]: cfg = 'env = PATH=/usr/bin:$PATH'
In[20]: print(cfg.partition('='))
('env ', '=', ' PATH=/usr/bin:$PATH')
In[21]: print(''.partition('='))
('', '', '')
In[22]: print('='.partition('='))
('', '=', '')
partition方法实现:
def partition(s, sep):
if s == '':
return '', '', ''
tmp = s.split(sep, maxsplit=1)
if len(tmp) == 2:
return tmp[0], sep, tmp[1]
if len(tmp) == 1:
return tmp[0], sep, ''
字符串大小写转换:
In[23]: s = 'my name is laven'
In[24]: print(s.capitalize())
My name is laven
In[25]: print(s.title())
My Name Is Laven
In[26]: print(s.lower())
my name is laven
In[27]: print(s.upper())
MY NAME IS LAVEN
In[28]: print(s.upper().lower())
my name is laven
In[29]: print('Hello World'.casefold()) # 不同的平台有不同的表现形式,但在同一平台下,表现形式相同,通常用来忽略大小写时的比较。
hello world
In[30]: print('Hello World'.swapcase())
hELLO wORLD
In[31]: print('\t'.expandtabs(4))
# 此处前面有四个空格
大小写转化通常用在做比较的时候,当我们需要忽略大小写的时候,通常统一转化为全部大写或全部小写再做比较。
字符串修改之填充:
s = 'my name is laven'
help(s.center) # 默认空格填充。如果宽度小于等于原串长度,不做任何操作。
s.center(80)
>>> s.center(80)
' my name is laven '
>>> s.center(80, '#')
'################################my name is laven################################'
>>>
# ljust方法
>>> s.ljust(80)
'my name is laven '
>>>
>>> s.ljust(80, '*') # 字符串左对齐
'my name is laven****************************************************************'
>>>
# rjust方法
>>> s.rjust(80)
'
>>> s.rjust(80, '*')
'****************************************************************my name is laven'
# ljust,rjust方法是针对字符串的显示位置的
# zfill方法
>>> s.zfill(80)
'0000000000000000000000000000000000000000000000000000000000000000my name is laven'
>>>
接下来演示3个非常重的字符串方法:strip、lstrip、rstrip:
s = ' hahe hehe \n \t'
s.strip()
>>> s.strip() # strip只能去掉字符串两边的空白或指定字符
'haha hehe'
# lstrip默认去掉前置的空白
>>> s.lstrip()
'haha hehe \n \t'
# rstrip默认去掉后置的空白
>>> s.rstrip()
' haha hehe'
# 去掉指定字符
>>> s = '##test##'
>>> s.strip('#')
'test'
>>> s.strip('*')
'##test##'
>>> s = '## test ##'
>>> s
'## test ##'
>>> s.strip('#')
' test '
>>> s.strip('#').strip()
'test'
strip方法可以移除指定的字符。大家可以试试看。
startswith与endswith方法,判断字符串是否以某个前缀开始,返回结果是boolean。
s = '**test##'
>>> s.startswith('*')
True
>>> s.endswith('#')
True
>>> s.endswith('test')
False
>>> s.endswith('test', 0, 5) # start,end 参数表示的是从索引start处开始到end处结束,但不包含end
False
>>> s.endswith('test', 0, 6)
True
字符查找与替换:
# count方法
s = '**test##'
>>> s.count('*')
2
>>> s.count('#')
2
>>> s.find('t') # find从左向右查找
2
>>>
>>> s.find('t')
2
>>> s.find('test')
2
>>> s.rfind('test') # rfind是find的从右向左查找的版本
2
>>> s.rfind('t')
5
s = 'i very very love python'
s.find('very') # 2
s.find('very', 3) # start参数指定从哪里开始查找
s.find('very', 3, 10) # end参数指定到哪里结束查找,end不包含
s.rfind('very') # 从右往左查找,但得到的索引是从左到右
# index方法,index一个不存在的字符或子串时,会报错;而find则不会报错;
>>> s.index('t')
2
>>> s.index('test')
2
>>> s.rfind('t')
5
>>> s.find('a')
-1
>>> s.index('a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found
s.find('a') # 使用find找一个不存在的字符,返回-1
s.index('a') # 使用index找一个不存在的字符,会抛出异常
# replace方法,可选的count,指定替换多少次
s = 'abc123abc123'
s.replace('abc', 'xyz') # 默认是全部替换,-1省略了
s.replace('abc', 'xyz', 1) # 只替换一次
s.replace('xxxx', '') # 如果要替换的字符不存在,什么都不做
s.replace('abc', 'xyz', -1) # -1表示全部替换
如果对find不是很理解,可以借助enumerate方法来查看,
In[32]: s = 'i very very love python'
In[33]: print(list(enumerate(s)))
[(0, 'i'), (1, ' '), (2, 'v'), (3, 'e'), (4, 'r'), (5, 'y'), (6, ' '), (7, 'v'), (8, 'e'), (9, 'r'), (10, 'y'), (11, ' '), (12, 'l'), (13, 'o'), (14, 'v'), (15, 'e'), (16, ' '), (17, 'p'), (18, 'y'), (19, 't'), (20, 'h'), (21, 'o'), (22, 'n')]
字符串判断函数是一些is开头的方法,这些方法用的不多。
一个比较有用的小技巧,
In[34]: line = 'url://http://lavenliu.cn'
In[35]: line.split(':', 1)
Out[35]: ['url', '//http://lavenliu.cn']
In[36]: key, value = line.split(':', 1)
In[37]: key
Out[37]: 'url'
In[38]: value
Out[38]: '//http://lavenliu.cn
splitlines方法:
In[39]: text = '''I am laven
...: I am a man
...: I like Emacs'''
In[40]: text.splitlines()
Out[40]: ['I am laven', 'I am a man', 'I like Emacs']
In[41]: text.splitlines(True) # 保留换行符
Out[41]: ['I am laven\n', 'I am a man\n', 'I like Emacs']
partition方法,
In[42]: s = 'my name is laven'
In[43]: s.partition(' ') # 类似于s.split(' ', 1)
Out[43]: ('my', ' ', 'name is laven')
In[44]: # 上面的line = 'url:http://magedu.com'可以写成如下的形式
In[45]: line.partition(':')
Out[45]: ('url', ':', '//http://lavenliu.cn')
In[46]: key, _, value = line.partition(':')
In[47]: key
Out[47]: 'url'
In[48]: value
Out[48]: '//http://lavenliu.cn'
In[49]: s.rpartition(' ')
Out[49]: ('my name is', ' ', 'laven')
字符串解包操作,
In[50]: s = 'my name is lavenliu'
In[51]: a, b, *mid, tail = s
In[52]: a
Out[52]: 'm'
In[53]: b
Out[53]: 'y'
In[54]: mid
Out[54]:
[' ',
'n',
'a',
'm',
'e',
' ',
'i',
's',
' ',
'l',
'a',
'v',
'e',
'n',
'l',
'i']
In[55]: tail
Out[55]: 'u'
字符串是也是可迭代的对象:
In[56]: s = 'hello world'
In[57]: for i in s:
...: print(i)
...:
h
e
l
l
o
w
o
r
l
d
In[58]:
In[1]: s = "use python do something"
In[2]: s[1], s[-1], s[1:6:2], s[1:], s[:-1], s[:]
Out[2]:
('s',
'g',
's y',
'se python do something',
'use python do somethin',
'use python do something')
In[3]: s[1:] # 从1开始到最后
Out[3]: 'se python do something'
In[4]: # 倒序
In[5]: s[::-1]
Out[5]: 'gnihtemos od nohtyp esu'
In[7]: s[4]
Out[7]: 'p'
字符串格式化是拼接字符的一种手段。如:
In[8]: print(' '.join(['i', 'love', 'python']))
i love python
In[9]: print('i' + ' love ' + 'python')
i love python
join
和+
拼接字符串难以控制格式。接下来介绍两种字符串格式化的方法。一种是printf-style方式一种是format方式。
首先介绍一下print函数的占位符及其说明,后面的讲解会用得到。
占位符 | 说明 |
---|---|
i | 有符号整数数 |
d | 有符号整数 |
o | 有符号的八进制数 |
x | 十六进制(以小写显示) |
X | 十六进制(以大写显示) |
e | 科学计数法(以小写显示) |
E | 科学计数法(以大写显示) |
f | 浮点数 |
F | 浮点数 |
语法为:
template % tuple
>>> 'I am %s' % ('lavenliu',) # 如果只有一个元素的时候,可以不用元组;即这里可以省略逗号,或直接省略小括号。
'I am lavenliu'
template % dict
>>> 'I am %(name)s' % {'name': 'lavenliu'}
'I am lavenliu'
>>>
>>> 'I am %(name)s, my name is %(name)s' % {'name': 'lavenliu'}
'I am lavenliu, my name is lavenliu'
# 使用字典的形式的场景
## 1. 反复出现
## 2. 需要格式化内容很多
一个简单的例子,
>>> a = "this is %s %s" % ("my", 'apple')
>>> print(a)
this is my apple
占位符的演示,
>>> '%i' % 18
'18'
>>> '%d' % 18
'18'
>>> '%ld' % 18 # 为了与C语言的兼容
'18'
>>> '%o' % 18
'22'
>>> '%X' % 12
'C'
>>> '%x' % 12
'c'
>>> '%e' % 0.00000345
'3.450000e-06'
>>> '%E' % 0.00000345
'3.450000E-06'
>>> '%e' % 12
'1.200000e+01'
>>> '%f' % 0.00000345 # 默认显示6位,不足就补0,多了就舍去
'0.000003'
# 如果只显示3位小数呢
'%0.3f' % 0.00123
'0.001'
>>> '%F' % 0.00000345
'0.000003'
# r与s的区别
class A:
def __str__(self):
return 'I am A.__str__'
def __repr__(self):
return 'I am A.__repr__'
a = A()
>>> a = A()
>>> '%s' % 123
'123'
>>> '%s' % a
'I am A.__str__'
>>> '%r' % a
'I am A.__repr__'
>>> '%a' % '\n'
"'\\n'"
# str是给人看的,repr是个机器看的
# a的演示
In[11]: '%a' % '\n'
Out[11]: "'\\n'"
In[10]: '%a' % '大川淘气'
Out[10]: "'\\u5927\\u5ddd\\u6dd8\\u6c14'"
当类型不匹配时,会抛出TypeError。当占位符是%s时,其实隐式调用了str()。
format语法,使用大括号作为占位符。当调用format方法时,format传入的参数会替换大括号。format方法的参数个数是可变的。
'I am {}'.format('lavenliu')
'I am {}, my age is {}'.format('lavenliu', 23) # 按照顺序
# 如果按照顺序呢
# 可以在占位符里加数字指定format参数的位置
'I am {1}, my age is {0}'.format('18, 'lavenliu'')
# 可以在占位符里加标识符,以使用关键字参数
'I am {name}, my age is {age}'.format(name='lavenliu', age=18)
# 多次出现也是可以的
'I am {name}, my name is {name}'.format('lavenliu')
'I am {0}, my name is {0}'.format('lavenliu')
# 几个好玩的用法
## 要么全是位置与关键字的
## 要么全是顺序与关键字的
## 位置的要在关键字之前
>>> '{1} {0} {name}'.format(1, 2, name='abc')
'2 1 abc'
>>> '{} {} {name}'.format(1, 2, name='abc')
'1 2 abc'
>>> '{0} {name} {1}'.format(1, 2, name='abc')
'1 abc 2'
>>> '{name} {} {}'.format(1, 2, name='abc')
'abc 1 2'
>>> '{} {name} {}'.format(1, 2, name='abc')
'1 abc 2'
# 这样写就会出错
## 顺序的,位置的,关键字的,不要混用
>>> '{} {1} {name}'.format(1, 2, name='abc')
ValueError: cannot switch from automatic field numbering to manual field specification
# 位置参数要在关键字参数之前
>>> '{} {name} {}'.format(1, name='abc', 2)
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
几个format的小例子,
In[12]: b = "this is {} {}" .format("my", "apple")
In[13]: print(b)
this is my apple
In[14]: ## {}里可以加入参数的位置
In[15]: b = "this is {1} {0}" .format("apple", "my")
In[16]: print(b)
this is my apple
In[17]: ## 更加高级的用法,这里不用指定数字,因为有可能算错位置
In[18]: b = "this is {whose} {fruit}" .format(fruit="apple", whose="my")
In[19]: print(b)
this is my apple
还可以使用类进行格式化,很吊的,
class A:
def __init__(self):
self.x = 1
self.y = 2
>>> a = A()
>>> a.x
1
>>> a.y
2
>>> '{0.x} {0.y}'.format(a)
'1 2'
>>> '{instance.x}'.format(instance=a)
'1'
可以使用列表进行格式化,
>>> lst = [1, 2, 3]
>>> '{0[0]}'.format(lst)
'1'
>>> '{lst[0]}'.format(lst=lst)
'1'
再来看几个例子,主要涉及格式化时的对齐操作,
# < 左对齐
>>> '{0:<80}'.format('lavenliu')
'lavenliu '
# > 右对齐
>>> '{0:>80}'.format('lavenliu')
# ^ 居中对齐
'{0:^80}'.format('lavenliu')
# 默认的,字符串对齐方式是左对齐
'{0:80}'.format('lavenliu')
# 默认的,数字对齐方式是右对齐
'{0:80}'.format(10)
# 数字
'{0:d}'.format(10)
'{:n}'.format(1000)
'{:b}'.format(10)
# 还可以嵌套
>>> '{0:^{width}}'.format('lavenliu', width=80)
' lavenliu '
>>> '{0:#^{width}}'.format('lavenliu', width=80)
'#####################################lavenliu#####################################'
>>> '{0:{fill}^{width}}'.format('lavenliu', width=80, fill='*')
'*************************************lavenliu*************************************'
printf-style格式化对于从其他语言,尤其是C语言转过来的,非常容易接受,但是Python并不推荐这种方法。 尽量使用内置的这种format的方式来格式化字符串。
另外,也可以使用字典的方式实现字符串的格式化。
In[20]: a = "this is %(whose)s %(fruit)s" % {'whose': 'my', 'fruit': 'apple'}
In[21]: a
Out[21]: 'this is my apple'
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有