1.8检查字符集中是否包含某字符集中的字符,在以下几个例子中,也就是检查seq是否包含aset中的项,各函数中Any结尾是部分包含,也就是只要有其中元素就返回true,All结尾的是全部包含,必须包含所有才返回true。(这里的例子都是字符集,也就是以单个字符为单位,与字符的顺序无关)。
一般的这么写
>>> def containAny(seq,aset):
... for c in seq:
... if c in aset:return Ture
... return False
...
>>> a=['ee','etg4','g4g']
>>> b=['f3f','34f43']
>>> containAny(a,b)
False
使用迭代器代替for是更高级的方法,效率更高,但是代码易读性比较差,作者并不推荐,如下
>>> import itertools
>>> def cotainsAny2(seq,aset):
... for item in itertools.ifilter(aset.__contains__,seq):
... return True
... return False
...
>>> cotainsAny2(a,b)
False
对于这个问题,作者更推荐的是使用集合的方法
>>> a=[1,2,3,4]
>>> b=[1,2,3,3]
>>> def containsAll(seq,aset):
... return not set(aset).difference(seq)
...
>>> containsAll(a,b)
True
>>> containsAll(b,a)
False
而对于set的difference方法,是这样的
>>> set(a).difference(b)
set([4])
>>> set(b).difference(a)
set([])
相比于以上几种方式,作者更倾向于下一种方式,以下方式要调用两个字符串函数,这里先来介绍一下
① s.translate(table,str) 对字符串s移除str包含的字符,剩下的字符串按照table里的字符映射关系替换。table可以理解为转换表,比较'a' -> 'A', 'b'->'B'.
② tabel = string.maketrans('s1', 's2') s1 和 s2 的长度必须一致,maketrans生成一个转换表,若在s中有s1,则替换为s2,这个转换表是字符字符一个个对应的,没必要全部包含。(这里引自http://www.jb51.net/article/54404.htm)可以看一看。
>>> import string>>> notrans=string.maketrans('','')#这里这么写是没有映射,保留原有的字符串。
>>> def containsAny(astr,strset):
... return len(strset)!=len(strset.translate(notrans,astr))
...
>>> def containsAll(astr,street):
... return not street.translate(notrans,astr)
>>> string1='asdfg'
>>> string2='asdfghjkl'
>>> string3='ferver'
>>> containsAny(string1,string2)
True
>>> containsAny(string2,string1)
True
>>> containsAny(string3,string1)
True
>>> containsAll(string3,string1)
False
>>> containsAll(string1,string2)
False
>>> containsAll(string2,string1)
True
1.9简化字符串translate方法的使用,作者在这里写了一个工厂函数,这个可以替换可以删除,个人觉得替换还是用replace好,本人才疏学浅,搞不懂python闭包,各位可以百度,这里给出函数。
>>> import string
>>> def translator(frm='',to='',delete='',keep=None):
... if len(to)==1:
... to=to*len(frm)
... trans=string.maketrans(frm,to)
... if keep is not None:
... allchars=string.maketrans('','')
... delete=allchars.translate(allchars,keep.translate(allchars,delete))
... def translate(s):
... return s.translate(trans,delete)
... return translate
...
>>> digits_only=translator(keep=string.digits)
>>> digits_only('hello world:123456')
'123456'
>>> no_digits=translator(delete=string.digits)
>>> no_digits('hello world:123456')
'hello world:'
>>> replace_digits=translator(from=string.digits,to='*')
File "<stdin>", line 1
replace_digits=translator(from=string.digits,to='*')
^
SyntaxError: invalid syntax
>>> replace_digits=translator(frm=string.digits,to='*')
>>> replace_digits('hello world:123456')
'hello world:******'
1.10过滤字符串中不属于指定集合的字符,本节作者还是使用了string下的translate方法,只是将translate又一次封装,使他更加易用。
>>> import string
>>> allchars=string.maketrans('','')
>>> def makefilter(keep):
... delchars=allchars.translate(allchars,keep)
... def thefilter(s):
... return s.translate(allchars,delchars)
... return thefilter
...
>>> my_filter=makefilter('abc')
>>> my_filter('agenrgbtgcandnbnnnccccb')
'abcabccccb'
上面的写法对unicode字符串是无效的,鉴于对unicode字符串的问题,作者使用如下方式解决。
>>> class Keeper(object):
... def __init__(self,keep):
... self.keep=sets.Set(map(ord,keep))
... def __getitem__(self,n):
... if n not in self.keep:
... return None
... return unichr(n)
... def __call__(self,s):
... return unicode(s).translate(self)
...
>>> makefilter=Keeper
>>> myfilter=makefilter('abc')
>>> myfilter(u'wfwbwrgwecwrfbwfwcrgfbwrcfbcb')
u'bcbcbcbcb'