dodo

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Python的核心数据类型——字符串

常见字符串常量和表达式

操作 解释
s = ‘’ 空字符串
s = “dodo’s” 双引号和单引号
s = ‘d\no\p\td\x00o’ 转义序列
s = “””….””” 三重引号字符串块
s = r’\temp\dodo’ Raw字符串
s = b’dodo’ 字节字符串
s = u’dodo’ unicode字符串(仅在2.0+使用)
s1 + s2,s * 3 合并,重复
s[i],s[i:j],len(s) 索引,分片,长度
“a %s parrot” % kind 字符串格式化表达式
“a {0} parrot”.format(kind) 字符串格式化方法
s.find(‘ao’) 字符串方法调用:搜索
s.rstrip() 移除空格
s.replace(‘pa’,’xx’) 替换
s.split(“,”) 用展位符分隔为列表
s.isdigit() 内容判断
s.lower() 所有字符转换为小写
s.endswith(‘do’) 判断s字符串是否以do结束
‘dodo’.join(strlist) 在strlist中的每个元素之间插入dodo字符串
s.encode(‘latin-1’) Unicode编码等
for x in s : print(x) 迭代,成员关系
‘dodo’in s 判断dodo是否为字符串s的成员
[c * 2 for c in s] 迭代字符串s中每个字符重复一次至列表
map(ord,s) 迭代s中每个字符的ASCII代码

就像任意字符的集合一样,字符串是用来记录文本信息的。ASCII是Unicode文本的一种简单形式。Python通过包含各种不同的对象类型,解决文本和二进制数据之间的区别:

  • 3.0+中,有3种字符串类型:str用于Unicode文本(ASCII或其他),bytes用于二进制数据(包括编码的文本),bytearray是bytes的一种可变的变体。
  • 2.0+中,Unicode字符串便是宽Unicode文本,str字符串处理8位文本和二进制数据。

bytearray类型在2.6+以后的版本中可用,更早的版本就不可用了,3.0+与二进制数据紧密相连。

字符串常量

  • 单引号:’spa”m’
  • 双引号:”spa’m”
  • 三引号:”””…spam…”””,’’’…spam…’’’
  • 转义字符:”s\tp\na\0m”
  • Raw字符串:r”c:\new\test.xxx”
  • Python3.0+中的Byte字符串:b’sp\x01am’
  • 仅在2.6中使用的Unicode字符串:u’eggs\u0020spam’

单双引号字符串是一样的

在Python字符串中,单引号和双引号是可以互换的。字符串常量表达式可以用两个单引号或两个双引号来表述——两种形式返回相同的类型对象。可以在双引号字符包含字符串中嵌入一个单引号字符(单引号则为字符串的一部分),反之亦然。

注意:字符串之间增加都好会创建一个元组,而不是字符串。

>>> "a",'b',"c",'d'
('a', 'b', 'c', 'd')

用转义字符代表特殊字节

转义序列让我们能够在字符串中嵌入不容易通过键盘输入的字节。字符串常量中字符”\“,以及在它后边的一个或多个字符,在最终的字符对象中会被一个单个字符所替代,这个字符通过转义序列定义了一个二进制值。

字符串反斜杠字符

转义 意义
\newline 忽视(连续)
\\ 反斜杠(保留\)
\’ 单引号(保留’)
\” 双引号(保留”)
\a 响铃
\b 倒退
\f 换页
\n 换行(新行)
\r 返回
\t 水平制表符
\v 垂直制表符
\N{id} Unicode数据库ID
\uhhhh Unicode16位的十六进制值,4个16进制数字
\Uhhhhhhhh Unicode32位的十六进制值,八个16进制数字
\xhh 十六进制值
\ooo 八进制值
\0 Null(不是字符串结尾)
\other 不转义(保留)

python以十六进制显示非打印的字符。

>>> s = '\001\002\x03'
>>> s
'\x01\x02\x03'
>>> len(s)
3
>>> s = 's\tp\na\x00m'
>>> s
's\tp\na\x00m'
>>> len(s)
7
>>> print(s)
s       p
a
>>> x = 'c:\py\code'
>>> x
'c:\\py\\code'
>>> len(x)
10

raw字符串抑制转义

转义字符序列用来处理嵌入在字符串中的特殊字节编码是很合适的。有时候,为了引入转义字符而使用适应的反斜杠的处理会带来一些麻烦。例如:使用文件名参数来打开一个文件:

fp = open(‘c:\new\text.dat’,’w’)

问题是这有”\n“,他会识别为一个换行字符,并且”\t”会被一个制表符所替代,结果就是调用尝试打开一个名为c:(换行)ew(制表符)ext.dat的文件,而不是我们需要的结果。

这正是使用raw字符串所要解决的问题。如果字母r(大写或小写)出现在字符串的第一个引号的前面,它将会关闭转义机制。因此为了避免这种文件名的错误,记得在windows中增加字母r:

fp = open(r’c:\new\text.dat’,’w’)

>>> path = r'c:\new\text.dat'
>>> path
'c:\\new\\text.dat'
>>> print(path)
c:\new\text.dat
>>> len(path)
15

除了windows文件夹路径,raw字符串也在正则表达式(文本模式匹配)中常见。

>>> x = r'1\nb\t\c\\'[:-1]
>>> x
'1\\nb\\t\\c\\'
>>> x = r'1\nb\t\c\\'
>>> x
'1\\nb\\t\\c\\\\'

注意:尽管有用,一个raw字符串也不能以单个的反斜杠结尾,因为反斜杠会转义后续引用的字符,仍然必须转义外围引号字符以将其嵌入到该字符串中。也就是说,r”…\”不是一个有效的字符串常量,一个raw字符串不能以奇数个反斜杠结束。如果需要用单个反斜杠结束一个raw字符串,可以使用两个反斜杠并分片掉第二个反斜杠(r’1\nb\t\c\\’[:-1])\手动添加一个反斜杠(r’1\nb\tc’+’\\’),或者忽略raw字符串语法在常规字符串中把反斜杠改为双反斜杠(‘1\\nb\\tc\\’)。以上三种形式都会创建同样的8个字符的字符串,其中包含3个反斜杠。

三重引号编写多行字符串块

Python中还有一种三重引号内的字符串常量格式,称作块字符串,这是一种编写多行文本数据的便捷语法。这个形式是以三重引号开始(单引号和双引号都可以),并紧跟任意行数的文本,以开始时同样的三重引号结尾。

  • 三重引号字符串在程序需要出入多行文本的任何时候都何有用的。例如:嵌入多行错误信息或源文件中编写html和xml代码等。
  • 三重引号字符串常用于文档字符串,当它出现在文件的特定地点时,被当做注释一样的字符串常量。这并非只能使用三重引号的文本块,但是他们往往是可以用作多行注释的。
  • 三重引号字符串经常在开发中飞出一些代码。如果希望让一些代码不工作,之后再运行代码,可以简单地在这几行前、后加入三重引号。

实际应用中的字符串

 

序列的操作

从严格意义上来说,字符串是单个字符的字符串的序列,其他类型的序列还包括列表和元组。

作为序列,字符串支持其中各个元素包含位置顺序的索引操作。

>>> s = 'yexiaodong'
>>> len(s) #长度
10
>>> s[0] #第一个字符
'y'
>>> s[1]#第二个字符
'e'
>>> s[-1] #倒数第一个字符
'g'
>>> s[-2] #倒数第二个字符
'n'
>>> s[len(s) - 1] #倒数第一个字符,同s[-1]
'g'

同样,也支持分片(slice),合并以及重复等操作。

image

偏移和分片:位置偏移从左至右(偏移0位第一个元素),而负偏移是有末端右侧开始计算(偏移-1位最后一个元素)。

索引(s[i])获取特定偏移的元素:

  • 第一个元素的偏移位0
  • 负偏移索引意味着从最后或右边反向进行计数
  • s[0]获取第一个元素
  • s[-2]获取了倒数第二个元素(就像s[len(s)-2]一样)

分片(s[i:j])提取对应的部分作为一个序列:

  • 上边界并不包含在内
  • 分片的边界默认为0和序列的长度,如果没有给出的话
  • s[1:3]获取了从偏移位1的元素,直到但不包括偏移为3的元素。
  • s[1:]获取了偏移为1直到末尾(偏移为序列长度)之间的元素。
  • s[:3]获取了从偏移为0直到但是不包括偏移为3之间的元素。
  • s[:-1]获取了从偏移为0直到但是不包括最后一个元素之间的元素。
  • s[:]获取了从偏移为0到末尾之间的元素,这有效地实现完全的顶层的序列s的拷贝——一个有相同值得序列。

扩展分片:第三个限制值:完整形式的分片变成s[i:j:k]。这表示索引s对象中的元素,从偏移为i直到偏移为j-1,每隔k元素索引一次。第三个限制值k,默认为1。

  • s[1:10:2]会取出s中偏移1-9之间,间隔了一个元素的元素,也就是手机偏移值为1、3、5、7、9之处的元素。
  • s[::2]会取出序列从头到尾、每隔一个元素的元素。
  • s[::-1]表示步进为-1的分片会从右至左进行。例如:”hello”[::-1]是返回一个新的字符串”olleh“。
  • s[5:1:-1]以反转的顺序获取从2到5的元素(结果是偏移5、4、3、2),例如:’abcdefg’[5:1:-1]的值为‘fdec’
>>> s[1:] #从第二个字符到最后进行分片
'exiaodong'
>>> s
'yexiaodong'
>>> s[0:3] #从第一个字符到第三个字符进行分片
'yex'
>>> s[:-1]#从第一个字符到倒数第二个字符进行分片
'yexiaodon'
>>> s[:] #复制
'yexiaodong'
>>> s + 'xyz' #字符串连接
'yexiaodongxyz'
>>> s
'yexiaodong'
>>> s * 3 #字符串重复
'yexiaodongyexiaodongyexiaodong'

类型的特定方法

除了一般的序列操作,字符串还有独有的一些操作作为方法存在。例如find方法是一个基本的字符串查找(返回一个传入子字符串的偏移量,或者没有找到返回-1),而replace方法将对全局进行搜索和替换。

>>> s = 'yexiaodong'
>>> s
'yexiaodong'
>>> s.find('ao') #找到返回偏移量
4
>>> s.replace('ao','XYZ') #替换为新的字符串
'yexiXYZdong'
>>> s
'yexiaodong'
>>> line = "aaa,bbb,cc,dddd"
>>> line.split(',')  #转换为列表
['aaa', 'bbb', 'cc', 'dddd']
>>> s = 'yexiaodong'
>>> s.upper() #所有字符大写
'YEXIAODONG'
>>> s.isalpha() #判断格式,isalpha,isdigit等
True
>>> line = 'aaa,bbb,cc,dddd\n'
>>> line
'aaa,bbb,cc,dddd\n'
>>> line = line.rstrip() #移除右边的特殊字符
>>> line
'aaa,bbb,cc,dddd'
>>> '%s,eggs,and %s' % ('apple','banana') #格式化输出
'apple,eggs,and banana'
>>> '{0},eggs,and {1}'.format('apple','banana')#格式化输出
'apple,eggs,and banana'

>>> x = 'A\nB\tC' #\n为换行符,\t为tab 字符长度都为1
>>> x
'A\nB\tC'
>>> len(x)
5
>>> ord('a') #a在ASCII中的代码
97
>>> ord('\n')#\n在ASCII中的代码
10
>>> x = 'A\0B\0C'  #\0,二进制0
>>> len(x)
5
>>> len('\0')
1
>>> msg = """ aaaaaa
... bbb'''bbbbbbbb""bbbbb'bbbb
... ccccccccccccccccc"""
>>> msg    #多行输入,可以看到被转义的字符
' aaaaaa\nbbb\'\'\'bbbbbbbb""bbbbb\'bbbb\n\nccccccccccccccccc'

不可变性

一旦字符串被创建就不能对原始的字符串进行改变。其他核心类型中,数字、元组也是不可变的。

>>> s
'yexiaodong'
>>> s[0] = 'A'    #不能对某一字符进行改变,否则会报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> s = 'A' + s[1:]   #除非创建新的字符串被引用
>>> s
'Aexiaodong'

字符串转换

  • python不能够将数字和字符串相加,甚至是看起来像数字的也不可以(如全数字的字符串)
  • int函数将字符串格式表达式转换为数字,而str函数将数字转换为字符串表达形式,repr函数(3.0+删除)也可以把数字转换为字符串。
  • str函数可以把浮点数转换为字符串,同样float函数也可以把字符串格式表达式转换为浮点数。
  • 字符串代码转换:ord函数转换为单个字符对应的ASCII码,chr函数将会获取ASCII码转换为字符。
>>> int("42"),str(42)
(42, '42')
>>> s = '42'
>>> i = 1
>>> s + i
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
>>> int(s) + i
43
>>> s + str(i)
'421'
>>> str(3.1415),float('1.5')
('3.1415', 1.5)
>>> text = "1.2345E-10"
>>> float(text)
1.2345e-10
>>> ord('s')
115
>>> chr(115)
's'
>>> s = '5'
>>> s = chr(ord(s) + 1)
>>> s
'6'
>>> s = chr(ord(s) + 1)
>>> s
'7'
>>> int('5')
5
>>> ord('5') - ord('0')
5
>>> b = '1101'   
>>> i = 0
>>> while b != '':   #将一个二进制数的字符串转换为等值的整数,即每次将当前值乘以2,并加上下一位数字的整数值。
...     i = i * 2 + (ord(b[0]) - ord('0'))
...     b = b[1:]
>>> i
13
>>> int('1101',2) #二进制转十进制
13
>>> bin(13) #十进制转二进制
'0b1101'

修改字符串

由于字符串是不可变,不能再原地修改一个字符串。

  • 若要改变一个字符串,需要利用合并,分片这样的工具来建立并赋值给一个新的字符串,倘若有必要的话,可以将结果赋值给字符串最初的变量名。
  • 可以通过像replace函数修改
>>> s = 'spam'
>>> s = s + 'SPAM!'
>>> s
'spamSPAM!'
>>> s = s[:4] + 'Burger' + s[-1]
>>> s
'spamBurger!'
>>> s = 'splot'
>>> s = s.replace('pl','pamal')
>>> s
'spamalot'

字符串方法

除表达式运算符以外,字符串还提供了一系列的方法去实现更复杂的文本处理任务。

python3.0+中的字符串方法

 

方法 描述
s.capitalize() 将字符串的第一个字母变成大写,其他字母变小写。
s.center(width[, fillchar]) 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串。默认填充字符为空格。width -- 字符串的总宽度,fillchar -- 填充字符。
s.count(sub[, start[, end]]) 统计字符串里某个字符出现的次数。可选参数为在字符串搜索的开始与结束位置。sub -- 搜索的子字符串,start -- 字符串开始搜索的位置。默认为第一个字符,第一个字符索引值为0,end -- 字符串中结束搜索的位置。字符中第一个字符的索引为 0。默认为字符串的最后一个位置。
s.encode(encoding="utf-8", errors="strict") 返回转换编码后的字符串。参数s是要转换内容的对象;encoding -- 要使用的编码,如"UTF-8";errors -- 设置不同错误的处理方案。默认为 'strict',意为编码错误引起一个UnicodeError。 其他可能得值有 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 以及通过 codecs.register_error() 注册的任何值。
s.decode(encoding='UTF-8', errors='strict') 以 encoding 指定的编码格式解码字符串。默认编码为字符串编码。encoding -- 要使用的编码,如"UTF-8";errors -- 设置不同错误的处理方案。默认为 'strict',意为编码错误引起一个UnicodeError;其他可能得值有 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 以及通过 codecs.register_error() 注册的任何值。
s.endswith(suffix[, start[, end]]) 判断字符串是否以指定后缀结尾,如果以指定后缀结尾返回True,否则返回False。可选参数"start"与"end"为检索字符串的开始与结束位置。suffix -- 该参数可以是一个字符串或者是一个元素。start -- 字符串中的开始位置。end -- 字符中结束位置。
s.expandtabs(tabsize=8) 把字符串中的 tab 符号('\t')转为空格,tab 符号('\t')默认的空格数是 8。tabsize -- 指定转换字符串中的 tab 符号('\t')转为空格的字符数。
s.find(str, beg=0, end=len(s)) 检测字符串中是否包含子字符串str,如果指定beg(开始)和end(结束)范围,则检查是否包含在指定范围内,如果包含子字符串返回开始的索引值,否则返回-1。str -- 指定检索的字符串,beg -- 开始索引,默认为0,end -- 结束索引,默认为字符串的长度。
s.index(str, beg=0, end=len(s)) 检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,该方法与 python find()方法一样,只不过如果str不在 s中会报一个异常。str -- 指定检索的字符串。beg -- 开始索引,默认为0。end -- 结束索引,默认为字符串的长度。
s.isalnum() 检测字符串是否由字母和数字组成。如果s至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False。
s.isalpha() 检测字符串是否只由字母组成。如果字符串至少有一个字符并且所有字符都是字母则返回 True,否则返回 False。
s.isdecimal() 检查字符串是否只包含十进制字符。这种方法只存在于unicode对象。注意:定义一个十进制字符串,只需要在字符串前添加 'u' 前缀即可。如果字符串是否只包含十进制字符返回True,否则返回False。
s.isdigit() 检测字符串是否只由数字组成。如果字符串只包含数字则返回 True 否则返回 False。
s.islower() 检测字符串是否由小写字母组成。如果字符串中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False
s.isnumeric() 检测字符串是否只由数字组成。这种方法是只针对unicode对象。注:定义一个字符串为Unicode,只需要在字符串前添加 'u' 前缀即可。如果字符串中只包含数字字符,则返回 True,否则返回 False。
s.isspace() 检测字符串是否只由空格组成。如果字符串中只包含空格,则返回 True,否则返回 False。
s.istitle() 检测字符串中所有的单词拼写首字母是否为大写,且其他字母为小写。如果字符串中所有的单词拼写首字母是否为大写,且其他字母为小写则返回 True,否则返回 False.
s.isupper() 检测字符串中所有的字母是否都为大写。如果字符串中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False
s.join(seq) 以 s作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串。
s.ljust(width) 返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串。width -- 指定字符串长度。fillchar -- 填充字符,默认为空格。
s.lower() 返回将字符串中所有大写字符转换为小写后生成的字符串。
s.lstrip([chars]) 返回截掉字符串左边的空格或指定字符后生成的新字符串。chars --指定截取的字符,默认为空格。
string.maketrans(intab, outtab]) 创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。注:两个字符串的长度必须相同,为一一对应的关系。返回字符串转换后生成的新字符串。通过from string import maketrans调用
max(s) 返回字符串中最大的字母。
min(s) 返回字符串中最小的字母。
s.partition(str) 用来根据指定的分隔符将字符串进行分割。如果字符串包含指定的分隔符,则返回一个3元的元组,第一个为分隔符左边的子串,第二个为分隔符本身,第三个为分隔符右边的子串。
s.replace(old, new[, max]) 返回字符串中的 old(旧字符串) 替换成 new(新字符串)后生成的新字符串,如果指定第三个参数max,则替换不超过 max 次。old -- 将被替换的子字符串。new -- 新字符串,用于替换old子字符串。max -- 可选字符串, 替换不超过 max 次
s.rfind(str, beg=0,end=len(s) ) 返回字符串最后一次出现的位置,如果没有匹配项则返回-1。str -- 查找的字符串。beg -- 开始查找的位置,默认为0。end -- 结束查找位置,默认为字符串的长度。
s.rindex( str, beg=0,end=len(s)) 返回子字符串 str 在字符串中最后出现的位置,如果没有匹配的字符串会报异常,你可以指定可选参数[beg:end]设置查找的区间。str -- 查找的字符串。beg -- 开始查找的位置,默认为0。end -- 结束查找位置,默认为字符串的长度。
s.rjust(width[, fillchar]) 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串。如果指定的长度小于字符串的长度则返回原字符串。width -- 指定填充指定字符后中字符串的总长度。fillchar -- 填充的字符,默认为空格。
s.rpartition(str) 类似于 partition()函数,不过是从右边开始查找。
s.rstrip([chars]) 删除 string 字符串末尾的指定字符(默认为空格)。chars -- 指定删除的字符(默认为空格)
s.split(str=""[, num]) 通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串,返回分割后的字符串列表。str -- 分隔符,默认为空格。num -- 分割次数。
s.splitlines([keepends]) 按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。keepends -- 在输出结果里是否去掉换行符('\r', '\r\n', \n'),默认为 False,不包含换行符,如果为 True,则保留换行符。
s.startswith(str,beg=0,end=len(string)) 检查字符串是否是以指定子字符串开头,如果是则返回 True,否则返回 False。如果参数 beg 和 end 指定值,则在指定范围内检查。str -- 检测的字符串。beg -- 可选参数用于设置字符串检测的起始位置。end -- 可选参数用于设置字符串检测的结束位置。
s.strip([chars]) 返回移除字符串头尾指定的字符(默认为空格换行等空字符)生成的新字符串。chars -- 移除字符串头尾指定的字符。
s.swapcase() 返回大小写字母转换后生成的新字符串。
s.title() 返回"标题化"的字符串,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle())。
s.translate(table[, deletechars]) 根据参数table给出的表(包含 256 个字符)转换字符串的字符, 要过滤掉的字符放到 del 参数中,返回翻译后的字符串。。able -- 翻译表,翻译表是通过maketrans方法转换而来。deletechars -- 字符串中要过滤的字符列表。
s.upper() 返回小写字母转为大写字母的字符串。
s.zfill(width) 返回指定长度的字符串,原字符串右对齐,前面填充0。width -- 指定需要返回字符串的长度。原字符串右对齐,前面填充0。
>>> s = 'goodpython'
>>> s.capitalize()
'Goodpython'
>>> s.center(50,'_')
'____________________goodpython____________________'
>>> s.count('o')
3
>>> s.count('o',2)
2
>>> s.count('o',3,9) 
1
>>> x = '你好'
>>> a = x.encode('utf-8','strict')
>>> a.decode('utf-8','strict')
'你好'
>>> s.endswith('on')
True
>>> b = 'hello\tworld!'
>>> b
'hello\tworld!'
>>> b.expandtabs(tabsize=8)
'hello   world!'
>>> b.expandtabs(tabsize=2)
'hello world!'
>>> s
'goodpython'
>>> s.find('py')
4
>>> s.index('py')
4
>>> s.isalnum()
True
>>> s.isalpha()
True
>>> s.isdecimal()
False
>>> x = u'5644'
>>> x.isdecimal()
True
>>> s.isdigit()
False
>>> x.isdigit()
True
>>> s.islower()
True
>>> x.isnumeric()
True
>>> y = b'444'#非Unicode会报错
>>> y.isnumeric()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'bytes' object has no attribute 'isnumeric'
>>> y.isdigit()
True
>>> str = '-'
>>> seq = ('a','b','c')
>>> str.join(seq)
'a-b-c'
>>> s = 'http://www.cnblogs.com/dodoye/'
>>> s.partition('://')
('http', '://', 'www.cnblogs.com/dodoye/')
>>> str1 = 'ab c\n\nde fg\rkl\r\n'
>>> print(str1.splitlines())
['ab c', '', 'de fg', 'kl']
>>> print(str1.splitlines(True))
['ab c\n', '\n', 'de fg\r', 'kl\r\n']

字符串格式化表达式

Python中的字符串格式化可以以两种形式实现:

    • 字符串格式化表达式:这是从Python诞生的时候就有的最初的技术;基于C语言的”printf“模型,并且在大多数现有的代码中使用。
    • 字符串格式化方法调用:这是2.6+和3.0+新增加的技术,这是Python独有的方法,并且和字符串格式化表达式的功能有很大重叠。

格式化字符串:

  • 在%操作符的左侧放置一个需要进行格式化的字符串,这个字符串带有一个或多个嵌入的转换目标,都以%开头(如%d)
  • 在%操作符右侧放置一个(或多个,嵌入到元组中)对象,这些对象将会插入到左侧想让Python进行格式化字符串的一个(或多个)转换目标的位置上去
>>> 'That is %d %s bird!' % (1,'dead')
'That is 1 dead bird!'
>>> x = 'Ni'
>>> "The knights whow say %s!" % x
'The knights whow say Ni!'
>>> "%d %s %d you" % (1,'spam',4)
'1 spam 4 you'
>>> "%s---%s----%s"  % (42,3.14159,[1,2,3])
'42---3.14159----[1, 2, 3]'

字符串格式化代码:

代码 意义
s 字符串(或任何对象)
r s,但使用repr,而不是str
c 字符
d 十进制(整数)
i 整数
u 无号(整数)
o 八进制整数
x 十六进制整数
X 十六进制整数,但打印大写
e 浮点指数
E 浮点指数,但打印大写
f 浮点十进制
F 浮点十进制
g 浮点e或f
G 浮点E或F
% 常量%

事实上,在格式化字符串中,表达式左侧的转换目标支持多种转换操作,这些操作自有一套相当严谨的语法。通用结构看上去如下:

%[(name)][flags][width][.percision]typecode

在%和字符码之间,你可以进行以下的任何操作:放置一个字典的键;罗列出左对齐(-)、正负号(+)和补零(0)的标志位,给出数字的整体长度和小数点后的位数等。width和percision都可以编码为一个*,以指定它们应该从输入值的下一项中取值。

>>> x = 1234
>>> res = "integers:...%d...%-10d...%06d" %(x,x,x)
>>> res
'integers:...1234...1234      ...001234'

%e,%f,%g格式对浮点数的标示方法有所不同。

>>> x = 1.23456789
>>> x
1.23456789
>>> '%e | %f | %g' %(x,x,x)
'1.234568e+00 | 1.234568 | 1.23457'
>>> '%E' % x
'1.234568E+00'

对于浮点数来讲,通过指定左对齐、补零、正负号、数字位数和小数点后的位数,可以得到各种各样的格式化结果。

>>> '%-6.2f | %05.2f | %+06.1f' % (x,x,x)
'1.23   | 01.23 | +001.2'
>>> "%s" % x,str(x)
('1.23456789', '1.23456789')

基于字典的字符串格式化

字符串的个数化同时也允许左边的转换目标来引用右边字典中的键来提取对应的值。

>>> "%(n)d %(x)s" % {"n":1,"x":"spam"}
'1 spam'

其中(n)和(x)引用了右边字典中的键,并提取它们相应的值。生成类似HTML和XML的程序往往会利用这一技术。

>>> reply = """
... Greeting ...
... Hello %(name)s!
... Your age squared is %(age)s
... """
>>> values = {'name':'bob','age':40}
>>> print(reply % values)

Greeting ...
Hello bob!
Your age squared is 40

内置函数vars配合使用,这个函数返回的字典包含了所有在本函数电泳时存在的变量:

>>> food = 'spam'
>>> age = 40
>>> vars()
{'__builtins__': <module 'builtins' (built-in)>, 'food': 'spam', '__doc__': None
, '__name__': '__main__', '__package__': None, '__loader__': <class '_frozen_imp
ortlib.BuiltinImporter'>, 'values': {'age': 40, 'name': 'bob'}, 'age': 40, 'x':
1.23456789, '__spec__': None, 'reply': '\nGreeting ...\nHello %(name)s!\nYour ag
e squared is %(age)s\n'}
>>> values
{'age': 40, 'name': 'bob'}
>>> "%(age)d %(food)s" % vars()
'40 spam'

字符串格式化调用方法

和格式化表达式不同,格式化方法调用不是紧密地基于C语言的”printf“模型,并且它们的意图更详细而明确。字符串对象的format方法使用主体字符串作为模板,并且接受任意多个表示将要根据模板替换的值得参数。在主体字符串中,花括号通过位置(如:{1}或关键字{food})指出替换目标及将要插入的参数。

>>> template = '{0},{1} and {2}'
>>> template.format('spam','ham','eggs')
'spam,ham and eggs'
>>> template = '{motto},{pork},{food}'
>>> template.format(motto='spam',pork='ham',food='eggs')
'spam,ham,eggs'
>>> template = '{motto},{0},{food}'
>>> template.format('ham',motto='spam',food='eggs')
'spam,ham,eggs'
>>> '{motto},{0},{food}'.format(42,motto=3.14159,food=[1,2]) #可以临时创建,并且任意对象类型都可以替换
'3.14159,42,[1, 2]'

添加键、属性和偏移量

像%格式化表达式一样,格式化调用可以变得更复杂以支持更多高级用途。例如,格式化字符串可以指定对象属性和字典键——就像在常规的Python语法中一样,方括号指定字典键,而点表示位置或关键字所引用的一项的对象属性。

>>> import sys
>>> 'My {1[spam]} runs {0.platform}'.format(sys,{'spam':'laptop'})
'My laptop runs win32'
>>> 'My {config[spam]} runs {sys.platform}'.format(sys=sys,config={'spam':'lapto
p'})
'My laptop runs win32'
>>> somelist = list('SPAM')
>>> somelist
['S', 'P', 'A', 'M']
>>> 'first={0[0]},third={0[2]}'.format(somelist)
'first=S,third=A'
>>> 'first={0},third={0}'.format(somelist[0],somelist[-1])
'first=S,third=S'
>>> parts = somelist[0],somelist[-1],somelist[1:3]
>>> 'first={0},last={1},,middle={2}'.format(*parts)
"first=S,last=M,,middle=['P', 'A']"

添加具体格式化

可以在格式化字符串中添加额外的语法来实现更具体的层级。对于格式方法,我们在替换目标的标识之后使用一个冒号,后面跟着可以指定字段大小、对齐方式和一个特定类型编码的格式化声明。其形式结构:

{fieldname|coversionflag:formatspec}

语法是:

    • fieldname是指定参数的一个数字或关键字,后面跟着可选的”.name“或”[index]“成分引用。
    • Coversionflag可以r、s,或者a分别是在该值上对repr、str或ascii内置函数的一次调用。
    • formatspec指定了如何表示该值,包括字段宽度、对齐方式、补零、小数点精度等细节,并且以一个可选的数据类型编码结束。

冒号后的formatspec组成形式上的描述如下(方括号表示可选的组成,并且不能编写为常量):

[[fill]align][sign][#][0][width][.precision][typecode]

align可能是<、>、=、或^,分别表示左对齐、右对齐、一个标记字符后的补充或居中对齐。Formatspec也包含嵌套的,只带有{}的格式化字符串,它从参数列表动态地获取值(和格式化表达式中的*很相似)。

可用的类型编码列表,它们几乎与前面李处的以及%表达式中使用的那些完全重合,但是格式化方法还允许一个”b“类型编码用来以二进制格式显示整数(它等同于使用bin内置函数),允许一个”%“类型编码来显示百分比,并且使用唯一的”d“表示十进制的整数(而不是”i“或”u“)。

例如:{0:10}意味着一个10字符宽的字段中的第一个位置参数,{1:<10}意味着第二个位置参数在一个10字符宽度字段中左对齐,{0.platform:>10}意味着第一个参数的platform属性在10字符宽度的字段中右对齐:

>>> '{0:10} = {1:10}'.format('spam',123.4567)
'spam       =   123.4567'
>>> '{0:10}={1:10}'.format('spam',123.4567)
'spam      =  123.4567'
>>> '{0:>10}={1:<10}'.format('spam',123.4567)
'      spam=123.4567  '
>>> '{0.platform:>10}={1[item]:<10}'.format(sys,dict(item='laptop'))
'     win32=laptop    '
>>> '{0:e},{1:.3e},{2:g}'.format(3.14159,3.14159,3.14159)#格式化浮点数
'3.141590e+00,3.142e+00,3.14159'
>>> '{0:f},{1:.2f},{2:06.2f}'.format(3.14159,3.14159,3.14159)
'3.141590,3.14,003.14'
>>> '{0:X},{1:o},{2:b}'.format(255,255,255)#格式化二进制、八进制、十六进制
'FF,377,11111111'
>>> bin(255),int('11111111',2),0b11111111
('0b11111111', 255, 255)
>>> hex(255),int('FF',16),0xFF
('0xff', 255, 255)
>>> oct(255),int('377',8),0o377
('0o377', 255, 255)
#硬编码格式化字符串
>>> '{0:.2f}'.format(1/3.0)#默认显示多少位
'0.33''
>>> '%.2f' % (1/3.0)
'0.33'
>>> '{0:.{1}f}'.format(1/3.0,4) #硬编码显示4位
'0.3333'
>>> '%.*f' % (4,1/3.0)
'0.3333'

python还提供了一种新的内置format函数,它可以用来格式化一个单独的项。他是字符串格式化方法的一种更简洁的替代方法。

>>> '{0:.2f}'.format(1.2345)
'1.23'
>>> format(1.2345,'.2f')
'1.23'
>>> '%.2f' % 1.2345
'1.23'

从技术上讲,内置函数format运行主体对象的__format__方法,对于每个被格式化项目,str.format方法都是内部的。它仍然比最初的%表达式的对等体要冗长。

注意:字符串格式化方法扩展:添加针对数字的千分隔位法,它在3位一组之间插入逗号。

>>> '{0:d}'.format(999999999)
'999999999'
>>> '{0:,d}'.format(999999999)
'999,999,999'
>>> '{:,d} {:,d}'.format(999999999,8888888888)
'999,999,999 8,888,888,888'
>>> '{0:,.2f}'.format(99999.25646)
'99,999.26'

尽管格式化方法有时候需要更多的代码,它还是:

  • 拥有%表达式所没有的一些额外功能
  • 可以更明确地进行替代之引用
  • 考虑到操作符会有一个更容易记忆的方法名
  • 不支持用于单个和多个替代值大小写的不同语法
>>> '{0:b}'.format((2**16)-1)
'1111111111111111'
>>> '%b' % ((2*816) - 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: unsupported format character 'b' (0x62) at index 1
>>> bin((2**16) - 1)
'0b1111111111111111'
>>> '%s' % bin((2**16) - 1)[2:]
'1111111111111111'

 

可变类型能够在原处修改

如果一个对象是不可变的,你就不能再原处修改它的值,否则Python会报错。替代的办法就是,你必须运行代码来创建一个新的对象来包含这个新的值。Python中主要核心类型划分为如下两类:

  • 不可变类型(数字、字符串、元组、不可变集合):不可变的分类没有哪个对象类型支持原处修改,尽管我们总是可以运行表达式来创建新的对象并将其结果分配给变量。
  • 可变类型(列表、字典、可变集合):可变集合总是可以通过操作原处修改,而不是创建新的对象。尽管这样的对象可以复制,但原处修改支持直接修改。

一般来说,不可变类型有某种完整性,保证这个对象不会被程序的其他部分改变。

posted on 2016-11-21 12:01  dodo‘s  阅读(2258)  评论(3编辑  收藏  举报