注:本文所有代码均经过Python 3.7实际运行检验,保证其严谨性。
上次Python随笔2说的是Python内置序列函数之enumerate函数,今天接着讨论另外一个内置序列函数,zip函数。
在讨论zip函数之前,有必要在Python随笔2里面说的序列之外,再简单介绍一下几个术语:
可迭代对象iterable、迭代器iterator以及它们和序列sequence的关系。
1.Python中万物皆对象,可迭代对象可以看作是迭代器、生成器、序列等的统称。判断一个对象是否可迭代对象,有一个简单的方法,那就是看这个对象能否用for...in...语句来进行遍历循环,能遍历循环的就是可迭代对象,不能的话,就不是可迭代对象。
2.可迭代对象iterable包括以下类型:迭代器iterator、序列sequence、字典dictionary等。
3.迭代器大致可以看作是“消耗型”的一种特殊的可迭代对象,它只能被遍历一次。一般也不能直接查看其内部元素,而是要通过类似于list(iterator)这种方式才能查看。迭代器iterator还有一个子类generator,经常搭配yield使用。
好了,灯光师!摄影师!让我们的焦点再回到今天的主角zip函数上。
zip函数的具体语法是:
zip(*iterables)——创建一个聚合了来自每个可迭代对象中的元素的迭代器。它返回一个元组的迭代器。参数iterables代表可迭代对象,前面有个*号表示可迭代对象的数量不确定,可以只有一个,也可以有多个。
看下面的例子:
s1 = ['a', 'b', 'c']
s2 = ['你', '我', '他']
zipped = zip(s1) # zip()中的参数可以为2个。
zipped # zip()函数返回的对象zipped是一个迭代器iterator。
Out[23]: <zip at 0x2209d37e088> #无法直接查看zipped迭代器中的元素。
list(zipped) # 使用list()这种方式来查看zipped迭代器中的元素。
Out[24]: [('a',), ('b',), ('c',)]
zipped2 = zip(s1, s2) # zip()里有2个参数的情况。
list(zipped2)
Out[27]: [('a', '你'), ('b', '我'), ('c', '他')]
zip的中文意思是,拉上拉链。当zip()中有2个参数(参数为可迭代对象)时,很容易顾名思义,理解其含义了——假设zip()中的2个参数都是序列,每个序列都是一条拉链,使用了zip()函数后,拉上拉链后各个序列对应的关系如何就不难想象了。
zip()里的参数当然可以不止是2个,可以是3个,以及更多个。但是,正如拉拉链时的效果服从于“短板理论”,zip()最终的效果也取决于所有可迭代对象中的长度最小的那个。如下面的例子所示:
s1 = ['a', 'b', 'c']
s2 = ['你', '我', '他']
s3 = ['Are you ok?']
zipped = zip(s1, s2, s3)
list(zipped) #最短的可迭代对象长度只有1,所以最后只有一个元组。
Out[32]: [('a', '你', 'Are you ok?')]
zip函数常用于遍历多个序列,有时会和此前讲过的enumerate函数搭配使用,呈现出另外一种效果。
for i, (a, b) in enumerate(zip(s1, s2)): #zip这里和enumerate函数搭配使用。
print(f"{i}: {a}, {b}")
0: a, 你
1: b, 我
2: c, 他
zip函数不但能拉上拉链,还能拉下拉链,只是这种用法略显“玄幻”,出人意表:
zipped = [('a', '你'), ('b', '我'), ('c', '他')]
s1, s2 = zip(*zipped) #*zipped带星号的用法本文前半部分有讲。
s1
Out[41]: ('a', 'b', 'c')
s2
Out[42]: ('你', '我', '他')
小结
zip函数的用顾名思义(zip的中文意思是拉上拉链),很容易理解,以zip()中有2个序列(可迭代对象)为例,每个序列(可迭代对象)都是其中一条拉链,拉上后两个序列(可迭代对象)中的元素对应关系如何,很容易想象得到。
此外,zip函数搭配enumerate函数可以实现不同的效果;甚至还能实现拉下拉链的效果,只是此法略显“玄幻”罢了。
替换字符串
在Python里面修改字符串的某一位字符,有两种方法。
拿一个例子作说明:
有一个字符串abcdefg,把其中的g替换为A,得到新的字符串abcdefA。
方法一:使用字符串的str.relace方法。其具体语法是:
str.replace(old, new[, count])——返回字符串的副本,其中出现的所有字符串old都将被替换为new。如果给出了可选参数count,则只替换前count次出现的old字符串。
s = 'abcdefg'
s = s.replace('g', 'A')
s
Out[4]: 'abcdefA'
方法二:用re正则表达式模块中的re.sub方法,其具体语法是:
re.sub(pattern, repl, string)——在一个字符串string中,用repl替换所有匹配正则表达式pattern的子串,返回替换后的字符串。repl你是想将之替换到字符串里的单个字符。
import re
s = 'abcdefg'
re.sub(r'[g]', 'A', s)
Out[3]: 'abcdefA'
小结
如果只是单纯得替换1个字符串或者连续几个字符串这种轻操作,方法一str.relace方法足够了;如果想要非连续替换多种字符串格式,re.sub的强大必然不会令你失望。