所以你施舍的时候,不可在你前面吹号,像那假冒为善的人,在会堂里和街道上所行的,故意要得人的荣耀。我实在告诉你们,他们已经得了他们的上次。你施舍的时候,不要叫左手知道右手所作的。要叫你施舍的事行在暗中,你父在暗中察看,必然报答你。(MATTHEW 6:2-4)

字符串(4)

虽然已经对字符串有了了解,但,因为人对字符串的要求比较多,特别是在输出格式上,要满足一定的样式要求。

字符串格式化输出

什么是格式化?在维基百科中有专门的词条,这么说的:

格式化是指对磁盘或磁盘中的分区(partition)进行初始化的一种操作,这种操作通常会导致现有的磁盘或分区中所有的文件被清除。

不知道你是否知道这种“格式化”。显然,此格式化非我们这里所说的,我们说的是字符串的格式化,或者说成“格式化字符串”,表示的意思是:

格式化字符串,是C、C++等程序设计语言printf类函数中用于指定输出参数的格式与相对位置的字符串参数。其中的转换说明(conversion specification)用于把随后对应的0个或多个函数参数转换为相应的格式输出;格式化字符串中转换说明以外的其它字符原样输出。

这也是来自维基百科的定义。在这个定义中,是用C语言作为例子,并且用了其输出函数来说明。在Python中,也有同样的操作——print语句(Python 2)、print()函数(Python 3),此前我们已经了解一二了。此处将详述之。

如果将维基百科的定义再通俗化,所谓字符串格式化化,就是要先制定一个模板,在这个模板中某个或者某几个地方留出空位来,然后在那些空位填上字符串,并且在显示结果中,字符串要符合空位置所设定的约束条件。

那么,那些空位,需要用一个符号来表示,这个符号通常被叫做占位符(仅仅是占据着那个位置,并不是输出的内容)。

>>> "I like %s"
'I like %s'

在这个字符串中,有一个符号:%s,就是一个占位符,这个占位符可以被其它的字符串代替。比如:

>>> "I like %s" % "python"
'I like python'
>>> "I like %s" % "Pascal"
'I like Pascal'

这是曾经较为常用的一种字符串输出方式。注意“曾经”,言下之意,现在不怎么太提倡了。

的确如此,现在提倡使用.format(),这是自Python 2.6开始引入的。所以,从现在开始,本教程详细介绍string.format()的使用方法,而对用%进行格式化输出的方式,仅仅局限在上面的样式。读者在阅读其它代码的时候,也能遇到使用%的,那时候你心中默默说一句“落伍了”,然后翻译成string.format()即可。

.format()是字符串的一个方法。你在交互模式中,输入dir(str),会看到如下的内容:

>>> dir(str)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

这里所列出来的,就是字符串str的所有属性和方法。

在这里先下一点毛毛雨。在Python中一切皆对象,所谓对象,就是一个具体东西。桌椅板凳,花花草草,动物植物,包括人,还有程序要找的那个“对象”,都是对象(不用追求严格定义,暂且模模糊糊知道大概即可,大概都不知道,也无妨),凡是对象都有属性和方法(至于属性和方法的定义,待后面说明)。刚才用dir(str)所返回的结果,就是字符串的属性和方法。

在返回结果中,别的先不看,只看format。有你的慧眼找一找,有没有发现?

继续不要离开交互模式,输入:

>>> help(str.format)

这是要看字符串的format()方法的文档。只有通过阅读文档,我们才能了解它使做什么的。

返回结果是:

Help on method_descriptor:

format(...)
    S.format(*args, **kwargs) -> str

    Return a formatted version of S, using substitutions from args and kwargs.
    The substitutions are identified by braces ('{' and '}').

S.format(*args, **kwargs),重点看括号里面的,*args表示传入一种类型的参数,**arg表示传入另外一种类型的参数。

又遇到新名词——参数——还是不用搭理它,只管继续——因为“发展是硬道理”!

你暂且阅读文档,不理解也没关系。下面用示例来说明使用方法。

>>> "I like {0} and {1}".format("python", "canglaoshi")
'I like python and canglaoshi'

在交互模式中,输入了字符串"I like {0} and {1}",并且其中用{0}{1}占据了两个位置,它们就是占位符。然后使一个非常重要的点.

这个点.非常重要,它是从对象引出它的属性或方法的工具,就如同汉语中的“的”一样。

比如“老齐的爱好”,“老齐”是那个对象,“爱好”就是一个方法,两者中间的那个“的”就相当于一个英文的点.,于是可以写成老齐.爱好,就可以表明上述的含义了。

format("python", "canglaoshi")是字符串格式化输出的方法,传入了两个字符串,它们分别对应这"I like {0} and {1}"里的那两个占位符,而且使按照顺序对应的,即第一个参数传入的"pytohn",对应着{0},第二参数传入的"canglaoshi"对应着{1}

你还可以这样试试,就理解更深刻了。

>>> "I like {1} and {0}".format("python", "canglaoshi")
'I like canglaoshi and python'

请仔细观察找区别。

format()方法的返回值是一个字符串——`'I like python and canglaoshi'`。

再对照help(str.format)得到的文档,看一看,是不是理解文档的含义了呢?

一定要会阅读文档,这是学习语言的根本。

既然是“格式化”,就要指定一些格式,让输出的结果符合指定的样式。

>>> "I like {0:10} and {1:>15}".format("python", "canglaoshi")
'I like python     and      canglaoshi'

现在有格式了。{0:10}表示第一个位置,有10个字符那么长,并且放在这个位置的字符是左对齐;{1:>15}表示第二个位置,有15个字符那么长,并且放在这个位置的字符是右对齐。

>>> "I like {0:^10} and {1:^15}".format("python", "canglaoshi")
'I like   python   and   canglaoshi   '

现在是居中对齐了。

>>> "I like {0:.2} and {1:^10.4}".format("python", "canglaoshi")
'I like py and    cang   '

这个有点复杂,我们一点一点的解释。

{0:.2}说明是第一个位置,对应传入的第一个字符串。.2表示对于传入的字符串,截取前两个,并放到第一个位置,注意的是,在:后面和.号前面,没有任何数字,意思是该位置的长度自动适应即将放到该位置的字符串。

{1:^10.4}1说明是第二个位置,对应传入的第二个字符串。^表示放到该位置的字符串要居中;10.4表示该位置的长度是10个字符串那么长,但,即将放入该位置的字符串应该仅仅有4个字符那么长,也就是要从传入的字符串"canglaoshi"中截取前四个字符,即为"cang"

再看结果,对照上述解释。

format()中,除了能够传入字符串,还可以传入数字(包括整数和浮点数),而且也能有各种花样。

>>> "She is {0:d} years old and the breast is {1:f}cm".format(28, 90.1415926)
'She is 28 years old and the breast is 90.141593cm'

{0:d}表示在第一个位置放一个整数;{1:f}表示在第二个位置放一个浮点数,那么浮点数的小数位数,是默认的。下面在这个基础上,可以再做一些显示格式的优化。

>>> "She is {0:4d} years old and the breast is {1:6.2f}cm".format(28, 90.1415926)
'She is   28 years old and the breast is  90.14cm'

{0:4d}表示第一个位置的长度是4个字符,并且默认状态下,填充到该位置的整数是右对齐。

{1:6.2f}表示第二个位置的长度使6个字符,并且填充到该位置的浮点数要保留两位小数,默认也是右对齐。

>>> "She is {0:04d} years old and the breast is {1:06.2f}cm".format(28, 90.1415926)
'She is 0028 years old and the breast is 090.14cm'

{0:04d}{1:06.2f}与前述例子不同的在于在声明位置长度的数字前面多了0,其含义是在数字前面,如果位数不足,则补0

以上的输出方式中,我们只讨论了format(*args, **kwargs)中的*args部分。还有另外一种方式,则是与**kwargs有关的(关于这两种参数的含义,本教程后面有专门介绍)。

>>> "I like {lang} and {name}".format(lang="python", name="canglaoshi")
'I like python and canglaoshi'

一种被称为“字典格式化”,这里仅仅列一个例子。关于“字典”,本教程后续会有的。

>>> data = {"name":"Canglaoshi", "age":28}
>>> "{name} is {age}".format(**data)
'Canglaoshi is 28'

format()做字符串格式化输出,真的很简洁,堪称优雅。

format()毕竟只是字符串的方法之一,还有更多方法等待研究。

常用的字符串方法

字符串的方法很多,前面已经通过dir(str)查看过了。

那么多方法,不会一一介绍,要了解某个具体的含义和使用方法,最好是使用help()函数查看。再举例:

>>> help(str.isalpha)

Help on method_descriptor:

isalpha(...)
    S.isalpha() -> bool

    Return True if all characters in S are alphabetic
    and there is at least one character in S, False otherwise.

按照这里的说明,就可以在交互模式下进行实验。

>>> "python".isalpha()    #字符串全是字母,应该返回True
True
>>> "2python".isalpha()    #字符串含非字母,返回False
False

根据分隔符分割字符串

split()的作用是将字符串根据某个分割符进行分割。

>>> a = "I LOVE PYTHON"
>>> a.split(" ")
['I', 'LOVE', 'PYTHON']

这是用空格作为分割,得到了一个名字叫做列表(list)的返回值,关于列表的内容,后续会介绍。还能用别的分隔吗?

>>> b = "www.itdiffer.com"
>>> b.split(".")
['www', 'itdiffer', 'com']

去掉字符串两头的空格

有的朋友喜欢输入结束的时候敲击空格,比如让他输入自己的名字,输完了,他来个空格。有的则喜欢先加一个空格,总做的输入的第一个字前面应该空两个格。

这些空格是没用的。

Python考虑到有不少人可能有这个习惯,因此就帮助程序员把这些空格去掉。

方法是:

  • S.strip():去掉字符串的左右空格
  • S.lstrip():去掉字符串的左边空格
  • S.rstrip():去掉字符串的右边空格

例如:

>>> b = " hello "    #两边有空格
>>> b.strip()
'hello'
>>> b
' hello '

特别注意,原来的值没有变化,而是新返回了一个结果。

>>> b.lstrip()    #去掉左边的空格
'hello '
>>> b.rstrip()    #去掉右边的空格
' hello'

字符大小写的转换

对于英文,有时候要用到大小写转换。最有名驼峰命名,里面就有一些大写和小写的参合。如果有兴趣,可以来这里看自动将字符串转化为驼峰命名形式的方法

在Python中有下面一些字符串的方法,用来实现各种类型的大小写转化

  • S.upper():S中的字母大写
  • S.lower():S中的字母小写
  • S.capitalize():首字母大写
  • S.isupper():S中的字母是否全是大写
  • S.islower():S中的字母是否全是小写
  • S.istitle():S中字符串中所有的单词拼写首字母是否为大写,且其他字母为小写(标题都这么写)

看例子:

>>> a = "qiwsir,python" 
>>> a.upper()       #将小写字母完全变成大写字母
'QIWSIR,PYTHON'
>>> a               #原数据对象并没有改变
'qiwsir,python'
>>> b = a.upper()
>>> b
'QIWSIR,PYTHON'
>>> c = b.lower()   #将所有的字母变成小写字母
>>> c
'qiwsir,python'

>>> a
'qiwsir,python'
>>> a.capitalize()  #把字符串的第一个字母变成大写
'Qiwsir,python'
>>> a               #原数据对象没有改变
'qiwsir,python'
>>> b = a.capitalize() #新建立了一个
>>> b
'Qiwsir,python'

>>> a = "qiwsir,github"
>>> a.istitle()
False
>>> a = "QIWSIR"        #当全是大写的时候,返回False
>>> a.istitle()
False
>>> a = "qIWSIR"
>>> a.istitle()
False
>>> a = "Qiwsir,github"  #如果这样,也返回False
>>> a.istitle()
False
>>> a = "Qiwsir"        #这样是True
>>> a.istitle()
True
>>> a = 'Qiwsir,Github' #这样也是True
>>> a.istitle()
True

>>> a = "Qiwsir"
>>> a.isupper()
False
>>> a.upper().isupper()
True
>>> a.islower()
False
>>> a.lower().islower()
True

再探究一下,可以这么做:

>>> a = "This is a Book"
>>> a.istitle()
False
>>> b = a.title()     #这样就把所有单词的第一个字母转化为大写
>>> b
'This Is A Book'
>>> b.istitle()       #判断每个单词的第一个字母是否为大写
True

.join()拼接字符串

+能够拼接字符串,除了这个还有别的。

当然,+也不是什么情况下都能够如愿的。比如,将列表(关于列表,后续详细说,它是另外一种类型)中的每个字符(串)元素拼接成一个字符串,并且用某个符号连接,如果用“+”,就比较麻烦了(是能够实现的,麻烦)。

用字符串的.join()方法拼接字符串,也是一个好选择。

>>> b
'www.itdiffer.com'
>>> c = b.split(".")
>>> c
['www', 'itdiffer', 'com']
>>> ".".join(c)
'www.itdiffer.com'
>>> "*".join(c)
'www*itdiffer*com'

这种拼接,是不是简单呢?

虽然不能把所有方法穷尽,但读者完全可以仿照上述流程研究其它方法。

字符串的问题还要继续,因为中文和英文还有很大区别。


总目录   |   上节:字符串(3)   |   下节:字符编码

如果你认为有必要打赏我,请通过支付宝:[email protected],不胜感激。

results matching ""

    No results matching ""