笨办法学Python:字符串相关

字符串的变幻

这是一个系列文章,从一起玩Python开始通过learn python the hard way进行Python的入门学习,建议从Python分类进行阅读。


教程的第5、6、7次训练着重对格式化字符串、字符串运算和输出进行讲解,看起来仅仅是一些语法,找到语法的源头,可以一次性完成对字符串相关知识的了解。

格式化字符串、辅助符号(Ex5 & Ex8)

Exercise 5: More Variables and Printing中基于print函数做了格式化字符串的练习,教程中主要的三个格式化字符如下:

  • %r 就是是非常有用的一个,含义是“不管什么都打印出来”。String (converts any Python object using repr()).
  • %s String (converts any Python object using str()).
  • %d Signed integer decimal.

自己尝试实践的代码如下:

1
2
3
4
5
many = 10
name = 'Tom'
print "there are", many, "boys."
print "One of them is %s" %name
ptint 'Tom is good at English, he said "I have %d friends. " ' %many

课后习题里提到:Search online for all of the Python format characters.搜索了官方文档:格式化字符说明以及Tutorial中相关内容发现其实字符串部分远不止这些,还有更多复杂的用法。

根据上面的案例可知一个格式化字符串基本的格式是'%xxx' %yyy其中xxx为格式符,yyy为对应的变量说明。如果变量较多,还可以变形为'%x1 %x2' %(y1,y2)可以理解为前面是格式符,见到了中间的’%’就知道要对后面的内容进行格式化操作,后面需要转化的内容可能是变量,也可能是直接的数值、字符串等等。官方文档利用字典型的数据举了一个例子如下:

1
2
3
4
5
print '%(language)s has %(number)03d quote types.' % \
{"language": "Python", "number": 2}

# 结果如下
Python has 002 quote types.

可能出现的格式符一共有十六个,在官方文档:格式化字符说明有明确说明和解释。其中‘u’用于表示‘无符号整型数’,到这里还不够,因为对格式的控制不仅仅需要格式化字符,还有更细致的控制方法,从零开始利用Matplotlib作图举例 提到了一个autopct='%1.1f%%'的格式符,我们尝试一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
'%6.2f' %2.3
# 输出
' 2.30'

'%06.2f' %2.3
# 输出
'002.30'

'%1.1f' %2.3
# 输出
'2.3'

'%1.1f' %22.3
# 输出
'22.3'
'%02.1f' %223344.3222
# 输出
'223344.3'

'%02.1f' %2.3222
# 输出
'2.3'

'%07.1f' %2.3222
# 输出
'00002.3'

以最后一个说明,小数点后的1为数值小数点后的数值位数,前面的为总的字符位数(包含小数点),最前面的零表示位数不足用零补足。如果提供的字符超过了要求的位数不会做操作,上面的案例就有很多个。这也很好理解,因为这里输出的是基于数值的处理,小数位数可以截断,但是整数部分截断会影响到数值的大小。

语法结构类似于:

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

  • (name)为命名
  • flags可以有+,-,’ ‘或0。+表示右对齐。-表示左对齐。
  • ’ ‘为一个空格,表示在正数的左侧填充一个空格,从而与负数对齐。0表示使用0填充。
  • width表示显示宽度
  • precision表示小数点后精度

但这并不是标准语法的介绍内容,来源博客1|博客2|博客3

Exercise 8: Printing, Printing主要是对格式化字符串进行复习,不仅仅是%前面的部分可以利用变量实现,后面的部分也可以,自己实践的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
x1 = '%r %r %r'
x2 = '%s %s %s'
print x1 % ('nihao',123,'lalala')
print x2 % ('nihao',123,'lalala')

# 输出
'nihao' 123 'lalala'
nihao 123 lalala

y = 'what','is','this'
print x1 % y
print x2 % y

# 输出
'what' 'is' 'this'
what is this

type(y)

# 输出
tuple

注意y变量的类型是tuple而不是string,关于变量的类型,在后面的学习和文章中补充。

字符串的输出(Ex6 & Ex9)

字符串的嵌套

Exercise 6: Strings and Text在之前的练习基础上增加了字符串套字符串的情况,如下所示:

1
2
3
x = 'What is your %s ' %'name'
print x
print 'My mom asked him %r ' %x

x表示的本身就是一个格式化的字符串,在后面的输出语句中整体被调用。事实上可以理解为x的格式化字符串被处理完之后再被调用,应该可以

1
2
3
4
5
6
7
8
9
10
11
12
13
gender = "boy"
y = "I am not a good %s" %gender
yy = "my mum said %r " %y
yyy = "my grandpa said %s and I don't believe that %s" %(yy , y)

y #输出如下
'I am not a good boy'

yy #输出如下
"my mum said 'I am not a good boy' "

yyy #输出如下
"my grandpa said my mum said 'I am not a good boy' and I don't believe that I am not a good boy"

建议大家尝试把 %r 换成 %s 可以发现两者的细微差异,这也是str() 和 repr()的差异。

字符串的单引号和双引号

字符串内容需要被引号包裹,这个引号可以是单引号、双引号、三引号。这中间并没有非常明确说明一定在什么情况下用什么。事实上单引号和双引号可以混用,但是当输出的语句中本身就有引号时,单双引号的使用更容易识别配对。
三引号(可以是三个单引号或者三个双引号的配对)一般在换行时输出段落使用,但是也要根据使用情况而定,比如下面的例子:

1
2
3
4
5
6
7
8
9
10
11
yy = '''hello
world'''

yy
# 输出
'hello\nworld'

print yy
# 输出
hello
world

字符串的运算(Ex6 & Ex7)

加号与称号

Exercise 6: Strings and Text在最后提出了一个问题:Explain why adding the two strings w and e with + makes a longer string.

在官方文档的搜索结果的7.1. string — Common string operations给出了三个链接:

在第二个链接中阐述了字符串相关的方法,其中有提到针对字符串的运算符的含义。加号会自动把两个字符串连接起来。

Exercise 7: More Printing中提到的字符串的乘法在String Methods也有涉及,把一个字符串内容重复n次。

逗号

这一段代码里有一个逗号,在有逗号时和没有逗号时输出的结果是不同的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
end1 = "C"
end2 = "h"
end3 = "e"
end4 = "e"
end5 = "s"
end6 = "e"
end7 = "B"
end8 = "u"
end9 = "r"
end10 = "g"
end11 = "e"
end12 = "r"
# watch that comma at the end. try removing it to see what happens
print end1 + end2 + end3 + end4 + end5 + end6,
print end7 + end8 + end9 + end10 + end11 + end12

Stack Overflow找到了问题What’s ending comma in print function for?,官方文档The print statement给出了源头。

A ‘\n’ character is written at the end, unless the print statement ends with a comma. This is the only action if the statement contains just the keyword print.

在Python2中,使用print在末尾用逗号时表示和后面的内容在统一行输出。

转义字符(Ex10)

转义字符(escape sequence or excape characters)在计算机语言里是非常普遍的情况,因为一些特殊的字符有特殊的用途,输入这些字符并不会直接输出字符本身。所以需要转义字符告诉计算机,这时候要输出的是字符本身而不是这些字符承担的特殊功能。在官方文档的Regular expression operations部分有说明。

Regular expressions use the backslash character (‘\’) to indicate special forms or to allow special characters to be used without invoking their special meaning. This collides with Python’s usage of the same character for the same purpose in string literals; for example, to match a literal backslash, one might have to write ‘\\‘ as the pattern string, because the regular expression must be \, and each backslash must be expressed as \ inside a regular Python string literal.

一般来说需要转义的字符都在斜线后面,如果要转义斜线怎么办呢?就需要再加一条斜线,示例如下:

1
2
3
4
5
6
7
print '\\'
# 输出如下:
\

print '\\\\'
# 输出如下:
\\

官方文档中的转义字符部分在正则表达式中,正则表达式也是计算机的相对通用的知识点,该部分内容会在以后的文章中讲解。在这里记住一些常用的转义字符

Escape What it does 备注
\ Backslash (\) 反斜杠
\’ Single-quote (‘) 单引号
\” Double-quote (“) 双引号
\a ASCII bell (BEL) 响铃符
\b ASCII backspace (BS) 退格符
\f ASCII formfeed (FF) 进纸符
\n ASCII linefeed (LF) 换行符
\N{name} Character named name in the Unicode database (Unicode only) Unicode 数据库中的字符名,其中 name 就是它的名字
\r Carriage Return (CR) 回车符
\t Horizontal Tab (TAB) 水平制表符
\uxxxx Character with 16-bit hex value xxxx (u’’ string only) 值为 16 位十六进制值xxxx 的字符
\Uxxxxxxxx Character with 32-bit hex value xxxxxxxx (u’’ string only) 值为 32 位十六进制值xxxx 的字符
\v ASCII vertical tab (VT) 垂直制表符
\ooo Character with octal value ooo 值为八进制值ooo 的字符
\xhh Character with hex value hh 值为十六进制数 hh 的字符

需要注意的是,如果利用字符串转换,转义字符并不生效,会产生如下效果:

1
2
3
4
5
6
7
8
months = "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug"
'%r' % months
# 输出
"'Jan\\nFeb\\nMar\\nApr\\nMay\\nJun\\nJul\\nAug'"

'%s' % months
# 输出
'Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug'

关于print

Print在Python2.7中有两个相关内容:

彩蛋

Ex10的最后给出了一段很有意思的代码:

1
2
3
while True:
for i in ["/","-","|","\\","|"]:
print "%s\r" % i,

注意,这里的代码在Jupyter Notebook是看不到执行效果的,要写成py结尾的文件,在编辑器中执行。
‘\r’转义符是回车符,而’\n’是换行符。关于换行符与回车符有很多的讨论,官方文档也有解释
可以简单理解为来源

\r 和 \n 都是以前的那种打字机传承来的。
\r 代表回车,也就是打印头归位,回到某一行的开头。
\n代表换行,就是走纸,下一行。

声明: 本文转载需标明出处,禁止用于商业目的。

ChangeLog

161212 新建
161213 发布