python 探索(三) Python CookBook 文本处理 笔记

Python 文本处理,看完本博文对python cookbook的笔记,足够了。

请善用目录。

更多的,详细的会更新。

每次处理一个字符

每次处理一个字符的方法:list,for,列表推导,map(),sets.Set()
列表推导和map() 比较推荐,简洁。至于效率高不高,这里不知。
# -*- coding: cp936 -*-
import sets

mystr = "abcdefghijklmn"

def do_sth_with(c):
    print c

#method 1
#直接内建list,然后for遍历list的每个c
print "method 1"
list1 = list(mystr)
for c in list1:
    do_sth_with(c)

#method 2
#不创建list也能for遍历字符串的每个c
print "method 2"
for c in mystr:
    do_sth_with(c)
 
#method 3
#列表推导
print "method 3"
res = [do_sth_with(c) for c in mystr]

#method 4
#map映射
print "method 4"
res = map(do_sth_with,mystr)

#method 5
#set操作,也就set有& | - ^这些操作
magic_chars = sets.Set('abracadabra')
print "magic_chars : " + str(magic_chars)
poppins_chars = sets.Set('supercalifragilisticexpialidocious')
print "poppins_chars : "+str(poppins_chars)
print 'magic_chars和poppins_chars的交集:'+''.join(magic_chars & poppins_chars)
结果:
#1 ~4 都是打印a到n
method 5:
acrd



拓展阅读:
Python的函数参数传递:传值?引用?

Python 学习笔记 02 – List 推导式-zhoukeli2005-ChinaUnix博客

python内置函数map/reduce/filter - 云计算架构师-解占辉 - 51CTO技术博客

Python Sets.Set 的& | - ^ 等操作


字符和字符值之间的转换

关键函数:ord,chr,unichr,利用好map()。
# -*- coding: cp936 -*-

#ascii
print ord('a')
print chr(97)

#unicode
print ord(u'\u2020')
print repr(unichr(8224))

#把字符串变成各个字符的值的列表
print map(ord,'Hello Wolrd')

#反过来
print ''.join(map(chr,range(97,100)))
结果:
97
a
8224
u'\u2020'
[72, 101, 108, 108, 111, 32, 87, 111, 108, 114, 100]
abc


拓展阅读:
str()和 repr() (及 `` 操作符) - 51CTO.COM

测试一个对象是否是类字符串

推荐使用isStringLike()方法,这里被python的 鸭子判断法逗笑了。
# -*- coding: cp936 -*-

#最傻的方法,连unicode对象都无法通过,自己的str子类也无法通过
def isExactlyAString(anobj):
    return type(anobj) is type('')

#接近完美的方法,basestring是str和unicode的共同基类
#用户自定义类型也是应该从basestring派生
#美中不足的是python标准库的UserString无法通过,因为它不是从basestring派生
def isAString(anobj):
    return isinstance(anobj,basestring)

#退而求其次的方法,虽慢,但有效。行为判断!
#python的鸭子判断法,走路像鸭子,叫声像鸭子,那么我们就认为它是鸭子!
def isStringLike(anobj):
    try: anobj.lower() + anobj + ''
    except: return False
    else: return True

print isExactlyAString('a')
print isExactlyAString(u'a')
print isAString('a')
print isAString(u'a') #暂时找不到UserString使用教程
print isStringLike('a')
print isStringLike(u'a')
结果:
True
False
True
True
True
True


字符串对齐

python处理文本对齐:ljust,rjust,center
# -*- coding: cp936 -*-
#共生成20个字符
print '|','hej'.ljust(20),'|','hej'.rjust(20),'|','hej'.center(20),'|'
#还可以指定分隔字符
print '|','hej'.ljust(20,'#'),'|','hej'.rjust(20,'#'),'|','hej'.center(20,'#'),'|'
结果:
| hej                  |                  hej |         hej          |
| hej################# | #################hej | ########hej######### |
结果看到的首尾的空格是print , 造成的。 


去除字符串两端的空格

关键函数:lstrip(),rstrip(),strip() ,他们还能指定要去掉的字符(字符串)
# -*- coding: cp936 -*-
x = '                hej                 '
print '|',x.lstrip(),'|',x.rstrip(),'|',x.strip(),'|'
y = 'ababab xx bababa'
print '|',y.lstrip('ab'),'|',y.rstrip('ab'),'|',y.strip('ab'),'|'
结果:
| hej                  |                 hej | hej |
|  xx bababa | ababab xx  |  xx  |


合并字符串

以后再用+或者+=就剁手吧!因为字符串是不可改变对象,所以在用+或+=的时候,会产生大量的中间对象,它们不断被创建和丢弃,效率不高。
reduce其实和+或+=一样。
原则是:避免中间对象!用join!!
# -*- coding: cp936 -*-
l = ['a','b','c','d','e','f','g']
largeString = ''.join(l)
print largeString
结果:
abcdefg
 
拓展阅读:
Python print函数用法,print 格式化输出


将字符串逐字符或逐词反转

对于逐字符:很喜欢[::-1]这种靠步长来整的。
对于逐词汇:reverse 和 [::-1] 也有用!
最后的正则:(\s+) 匹配不是空白字符的字符串。
re.split(r('\s+'),s) 能够保留原来的空格。
# -*- coding: cp936 -*-
import re

s = 'Hello  World'
#步长为-1,表示从尾开始复制
print s[::-1]

#逐词
revwords = s.split()
revwords.reverse()
print ' '.join(revwords)

#逐词简约版
revwords = ' '.join(s.split()[::-1])
print  revwords

#正则版本,保留空格
revwords = re.split(r'(\s+)',s)
revwords.reverse()
revwords = ''.join(revwords)
print revwords

#正则简约版
revwords = ''.join(re.split(r'(\s+)',s)[::-1])
print revwords

#reversed 代替 [::-1]
revwords = ' '.join(reversed(s.split( )))
print revwords
revwords = ''.join(reversed(re.split(r'(\s+)',s)))
print revwords


检查字符串中是否包含某字符集合中的字符

这一节收获最大的是学会了一个思路:集合set,difference!
学会了一个装的艺术:maketrans 和 translate。

maketrans 和 translate的用法,简单说就是:

s = 'abcdefg-1234567' #原始字符
table = string.maketrans('abc', 'ABC') #把字符串中的abc字符集合映射成ABC字符集合
deltable = 'bc123' #待删除字符集合
s.translate(table,deltable) #s删除掉deltable的字符后,对着table映射
结果是:Adefg-4567
Ps:这两个货,仅仅限于普通字符串,连Unicode都不行

在判断str1是否包含str2某些元素的时候:

import string
notrans = string.maketrans('','') #意思是不做映射
def containsAny(str1,str2):
return len(str1) != len(str1.translate(notrans,str2))  #str1删除str2中元素后,若len值发生改变,返回True,被删除的是共同元素

在判断str1是否完全包含str2的时候:

import string
notrans = string.maketrans('','')
def containsAll(str1,str2):
return not str2.translate(notrans,str1)
如果str1完全包含str2,str2.translate(notrans,str1)会是一个空集合,not {} 就是True
如果str1不能全含str2,str2.translate(notrans,str1)会是一个非空集合{},,非空为True,not 非空就是False

# -*- coding: cp936 -*-

import itertools
import string

'''aset包含seq任意字符即可'''
#method 1 这是最朴素简单实用的短路法。
def containsAny(seq,aset):
    for c in seq:
        if c in aset: return True
    return False

#method 2 装逼写法,依旧短路法
def containsAny2(seq,aset):
    for item in itertools.ifilter(aset.__contains__,seq):
        return True
    return False

#method 3 装的艺术 - maketrans和translate
notrans = string.maketrans('','')
def containsAny3(astr,strset):
    return len(astr) != len(astr.translate(notrans,strset))

'''seq包含aset全部字符'''
#method 4 这也是最朴素简单实用的短路法
def containsAll(seq,aset):
    for c in aset:
        if c not in seq: return False
    return True

#method 5 set集合 difference 不是短路法,效率没3高
def containsAll2(seq,aset):
    return  not set(aset).difference(seq)

#method 6 装的艺术 - maketrans和translate
notrans = string.maketrans('','')
def containsAll3(astr,strset):
    return not strset.translate(notrans,astr)


str1 = 'abcdefg'
str2 = 'ghijklm'

str3 = 'abcdef'
str4 = 'abcd'

L1 = [1,2,3,3]
L2 = [1,2,3,4]

print containsAny(str1,str2)       #str1 contains any of str2 True 
print containsAny2(str1,str2)      #str1 contains any of str2 True

print containsAll(str3,str4)       #str3 contains all of str4 True 
print containsAll(str4,str3)       #str4 contains all of str3 False

print containsAll2(L1,L2)           #L1 contains aLL of L2 False
print containsAll2(L2,L1)           #L2 contains all of L1 True

print containsAny3(str1,str2)      #str1 contains any of str2 True 
print containsAll3(str3,str4)      #str3 contains all of str4 True  
print containsAll3(str4,str3)      #str4 contains all of str3 False 



拓展阅读:
Python:itertools模块
python之maketrans translate_阿雅菲菲儿_新浪博客

简化字符串的translate方法的使用

首次接触:工厂函数,闭包。
定义不说,直接上实例:
def line_conf(a,b):
    def line(x):
        return a*x + b
    return line

line1 = line_conf(1,1)
line2 = line_conf(4,5)
print line1(5),line2(5) #6 25
其中line_conf 这个函数为一个工厂函数,也可以称为闭包工厂,强调它创建并返回闭包(类似于C++函数指针?)。
说到这里,你应该猜到了,内层函数line(),由一个变量line来指代,这内层函数就是一个闭包。
博客园的Vamei这么说:一个函数和它的环境变量在一起,就可以被称为闭包。这里函数为line(),它的环境变量时a,b。

引入上面的概念是为了说一件事,Fred L.Drake,Jr 认为,translate 和 maketrans 很好用,但是老在用的时候想不起细节,耽误时间,所以自己写一个工厂函数,可以方便许多。
import string

#这是由Fred L.Drake,Jr 提供的 闭包工厂
#我觉得特别不错!!!忽略delete和keep同时存在的情况,因为那不科学
#如果真要同时存在,我认为分两次处理,才是科学的

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)
        delete = allchars.translate(allchars,keep.translate(allchars,delete))
    def translate(s):
        return s.translate(trans,delete)
    return translate

digits_only = translator(keep=string.digits)
print digits_only('aaaaa11111111aaaaa') #11111111

no_digits = translator(delete=string.digits)
print no_digits('aaaaa11111111aaaaa') #aaaaaaaaaa

#用字符替换某个集合的字符
digits_to_hash = translator(frm=string.digits,to='#')
print digits_to_hash('aaaaa11111111aaaaa') #aaaaa########aaaaa



拓展阅读:
Python深入04 闭包 - Vamei - 博客园

过滤字符串中不属于指定集合的字符

关键:我又找到一个给 字符去重和排序的方法了。
又一次闭包工厂!
import string

#这个只要translate取反keep即可
allchars = string.maketrans('','')
def makefilter(keep):
    delchars = allchars.translate(allchars,keep)
    def thefilter(s):
        return s.translate(allchars,delchars)
    return thefilter

#准备阶段
keep = makefilter('abc')
#执行阶段
print keep('abcdefgaaa') # abcaaa


#规整字符串,无重,排好序
def canonicform(s):
    return makefilter(s)(allchars)

s = 'aaaaaaaaaasldkfjgh'
print canonicform(s) #adfghjkls

#等同于
aa = makefilter(s)
print aa(allchars) #adfghjkls

可是!Unicode,不行!Unicode的translate 反而更加简单。
import string

#unicode translate 反而更加简单,就一个table,映射即可
tb = dict([ (ord(ch), None) for ch in u" aeiou"])
s = u'four score and seven years ago'
print s.translate(tb) #frscrndsvnyrsg

#本任务中考虑到str要被keep,而不是被del
#要有一个巨大的dict来标记想要的和不想要的!
#Fred L.Drake,Jr提供了一个特不错的方法(大神就是大神):

import sets
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 #重命名下
 
if __name__ == '__main__':
    just_vowels = makefilter('aeiouy')
    print just_vowels(u'four score and seven years ago')


检查一个字符串是文本还是二进制

我这个直接拓展成, 检查一个文件是文本文件还是二进制文件!
在istextfile中,切记,用"rb"打开。

Fred的想法好奇特:用启发式探索法来判断。最高位为1的概率,超过阈值%30就判断为二进制。

from __future__ import division #Fred说,这兼容未来?
import string

text_characters = "".join(map(chr,range(32,127))) + "\n\r\t\b"
_null_trans = string.maketrans("","")
def istext(s,text_characters=text_characters,threshold = 0.30):
    #threshold 阈值 
    #s包含了空值,不是文本,空值是文本的结束标志
    if "\0" in s:
        return False
    #逻辑判定:空字符串是文本
    if not s:
        return True
    print 'aa'   
    t = s.translate(_null_trans,text_characters)
    print len(t),len(s),len(t) / len(s)
    return  len(t) / len(s) <= threshold

def istextfile(filename,blocksize=512):
    return istext(open(filename,"rb").read(blocksize))

print istext("123123123123") #True
print istextfile('1.bin') #False
print istextfile('1.txt') #True


拓展阅读:
[Python学习]判断一个文件是文本还是二进制的 - limodou的学习记录

控制大小写

upper()            THIS IS OUYANG
lower()             this is ouyang
capitalize()      This is ouyang
title()                This Is Ouyang

哈,又看到喜闻乐见的 鸭子判断法

#检查字符串是不是符合 开头大写,其余小写的情况
import string

notrans = string.maketrans('','')
def containsAny(str,strset):
    return len(str) != len(str.translate(notrans,strset))

#还记得鸭子判断法吗?叫声像(能capitalize)+长得像(containsAny)。
def isCapitaliezd(s):
    return s == s.capitalize() and containsAny(s,string.letters)

s1 = 'This is ouyang...'
s2 = 'this is ouyang...'
print isCapitaliezd(s1) #True
print isCapitaliezd(s2) #False

拓展阅读:
Python String capitalize() Method

访问子字符串

本节接触了:
struct.unpack() 
zip()
封装 和 memoizing思想
python不会溢出
三元运算符 flag and 's' or 'x'  == flag?'s':'x'
yield (请看拓展阅读)
import struct

theline = 'abcdefghijklmnopqrstuvwxyz1234567890'

#struct.unpack()按照指定格式
baseformat = "5s 3x 8s 8s"
numremain = len(theline) - struct.calcsize(baseformat)
format = "%s %ds" % (baseformat,numremain)
l,s1,s2,t = struct.unpack(format,theline)
print l,s1,s2,t

#struct.unpack()这么优秀的东西 - 封装
def fields(baseformat,theline,lastfield = False):
    numremain = len(theline) - struct.calcsize(baseformat)
    #lastfield and 's' or 'x' == lastfield ? 's':'x'
    format = "%s %d%s" % (baseformat,numremain,lastfield and 's' or 'x')
    return struct.unpack(format,theline)

print 'lastField == True : ',fields(baseformat,theline,True)
print 'lastField == False : ',fields(baseformat,theline,False)

#struct.unpack()这么优秀的东西 - 封装 - memoizing 版本 - 字典做缓存
def fields_memoizing(baseformat,theline,lastfield = False,_cache={}):
    key = baseformat,len(theline),lastfield
    format = _cache.get(key)
    if format == None:
        numremain = len(theline) - struct.calcsize(baseformat)
        _cache[key] = format = "%s %d%s" % (baseformat,numremain,lastfield and 's' or 'x')
    return struct.unpack(format,theline)

print 'lastField == True : ',fields_memoizing(baseformat,theline,True)
print 'lastField == False : ',fields_memoizing(baseformat,theline,False)



#5字节一组,最后不足5字节也不会越界
fivers = [theline[k:k+5] for k in xrange(0,len(theline),5)]
print fivers

#5字节一组,最后不足5字节也不会越界 - 封装
def split_by(theline,n,lastfield):
    pieces = [theline[k:k+n] for k in xrange(0,len(theline),5)]
    #如果最后一段太短或不需要,丢弃
    if not lastfield and len(pieces[-1]) < n:
        pieces.pop()
    return pieces

print 'split_by lastField == True : ',split_by(theline,5,True)
print 'split_by lastField == False : ',split_by(theline,5,False)

#指定长度的切片,zip()打包成元组
cuts = [8,14,20,26,30]
pieces = [theline[i:j] for i,j in zip([0]+cuts,cuts+[None])]
print pieces

#指定长度的切片,zip()打包成元组 - 封装
def split_at(theline,cuts,lastfield):
    pieces = [theline[i:j] for i,j in zip([0]+cuts,cuts+[None])]
    #若不要最后一段,丢弃
    if not lastfield :
        pieces.pop()
    return pieces
print 'split_at lastField == True : ',split_at(theline,cuts,True)
print 'split_at lastField == False : ',split_at(theline,cuts,False)



在拓展阅读第二篇,南柯一梦介绍了 利用zip() 以指定概率获取元素,我觉得不错。
在拓展阅读第四篇,讲解了yield的用法,他让我明白了为什么引入yield。
#指定长度的切片,zip()打包成元组 - 封装 - yield 迭代对象
#这已经不是一个fun()了,而是一个generator(),返回一个迭代器对象
def split_at_yeild(theline,cuts,lastfield = True):
    last = 0
    for cut in cuts:
        yield theline[last:cut]
        last = cut
    if  lastfield:
        yield theline[last:]
    
for i in split_at_yeild(theline,cuts,True):
    print i



拓展阅读:
Python模块学习 ---- struct 数据格式转换
Python中zip()函数用法举例 | 南柯一梦

字典和元组——菜鸟的Python笔记

Python yield 使用浅析

改变多行文本字符串的缩进

关键:str.splitlines(False or True) ,为True的时候保留'\n'
#对齐
def reinent(s,numSpaces):
    leading_space = numSpaces * ' '
    lines = [leading_space + line.strip() for line in s.splitlines()]
    return '\n'.join(lines)

def addSpaces(s,numAdd):
    white = " "*numAdd
    return white + white.join(s.splitlines(True))

def numSpaces(s):
    return [len(line) - len(line.lstrip()) for line in s.splitlines()]

def delSpaces(s,numDel):
    if numDel > min(numSpaces(s)):
        raise ValueError,"删的空格比最小空格数大"
    return '\n'.join(line[numDel:] for line in s.splitlines())

x = """    line one
    line two
    and line three """

print x
print reinent(x,4)
print addSpaces(x,4)
print delSpaces(x,3)


拓展和压制制表符

关键词:enumerate() 是同时去index索引,和内容list[index]的内置函数。
关键词:expandtabs() 把tab转成空格
我认为,tab和空格的互转,一般是tab转空格,一个expandtabs()就足够了,空格转tab可能只出在考试题中。
#把tab转成空格
s = "a\t aaaaa\t         aaaa"
s1 = s.expandtabs()
print s,len(s) 	 
print s1,len(s1)

#把空格转成tab
def unexpand(s,tablen = 8):
    import re
    #切分成空格和非空格
    pieces = re.split(r'( +)',s.expandtabs())
    #记录当前字符串总长度
    lensofar = 0
    for i,piece in enumerate(pieces):
        thislen = len(piece)
        lensofar += thislen
        if piece.isspace():
            #把每个空格序列改成tab+spaces
            numtabs = (thislen-numblanks+tablen-1)/tablen
            print numblanks,numtabs
            pieces[i]='\t'*numtabs +' '*numblanks
    return ''.join(pieces)

s2 = unexpand(s1)
print s1,len(s1)
print s2,len(s2)


差点被路过的真相:python下用expandtabs(),会发现有的'\t'占8个,有的占4个,有的3个,总之很乱,我还以为是IDLE的问题。
刚刚手里吃着玉米,也不能编码,就谷歌:python expandtabs ,出现了 拓展阅读的第二篇。解答了我的疑惑。 
其实这都和拓展位有关。感谢同事和他递过来的玉米。

拓展阅读:
python天天进步(7)--enumerate用法 - 久月 - 博客园
字符串方法expandtabs和制表位(tabstops) | Shine.IT

替换字符串中的子串

任务要求是:某字符串中被标记的字符串要被按照字典,替换掉。
比如说:str = 'just "a" test'   dict = {'a':'one'} ,那么结果是:'just one test'
关键词:偶数项就是要替换的子字符串。
Ps:增加一个安全模式感觉很专业。
def expand(format,d,marker='"',safe = False):
    if safe:
        #dict.get(key[, default])
        def lookup(w):return d.get(w,w.join(marker*2))
    else:
        def lookup(w):return d[w]
    parts = format.split(marker)
    #偶数项 就是要替换的子字符串
    parts[1::2] = map(lookup,parts[1::2])
    return ''.join(parts)

format = 'just  a "a" "b" test '
print expand(format,{'a':'one','b':'two'})

#>>> 
#just  a one two test  
#>>>

还有个更加专业的做法:
Tem = string.Template('$thing')
Tem.substitute({'thing':5})

local() 内置函数,存储了本地变量

import string
new_style = string.Template('this is $thing')

print new_style.substitute({'thing':5})
print new_style.substitute({'thing':'test'})
print new_style.substitute(thing = 5)
print new_style.substitute(thing = 'test')

#local() 本地变量
msg = string.Template('the square of $number is $square')
for number in range(10):
    square = number * number
    print msg.substitute(locals())


一次完成多个替换

sub( pattern, repl, string[, count]) :用repl替换pattern匹配到的string,最多count次
其中,repl可以是string,也可以是func()
当repl是函数的时候,对每一个在string内的,不重叠的,匹配pattern的子串,调用repl(substring),然后用返回值替换substring
对于上述的黑体字,本人做了个小实验,实验代码:
import re

adict = {'a':'1','b':'2'}
s = 'abacabc'

print  '|'.join(map(re.escape,adict))
def multiple_replaces(text,adict):
    robj = re.compile('|'.join(map(re.escape,adict)))
    def one_xlat(match):
        print '###',match.group(0)
        return adict[match.group(0)]
    return robj.sub(one_xlat,text)

print multiple_replaces(s,adict)
实验结果:
>>> 
a|b
### a
### b
### a
### a
### b
121c12c
>>> 
明显发现:
(1)我们调用一次sub(),sub()内部就调用了5次one_xlat()。
(2)顺序是 a b a a b ,和s='abacabc'中a,b出现的顺序一致。
我猜测,按照s从左到右顺序,s被'a|b'匹配一次就替换一次,然后重头再匹配,所以s的生成历程是:
1bacabc
12acabc
121cabc
121c1bc
121c12c

match.gourp(0) :匹配整个表达式的字符串,group(i) 就表示第i个括号表达式匹配到的字符串

考虑到以后很多情况下,dict是固定的,其实我们只要做一次准备工作就够了。而上面的版本是用一次,准备一次。
很自然的想到闭包工厂!(在前几节有提到这概念)
我们就准备一次transalte,然后就能用translate去无限匹配替换text了。
import re

def make_xlat(*args,**kwds):
    adict = dict(*args,**kwds)
    rx = re.compile('|'.join(map(re.escape,adict)))
    def one_xlat(match):
        return adict[match.group(0)]
    def xlat(text):
        return rx.sub(one_xlat,text)
    return xlat

adict = {"a":"1","b":"2"}
translate = make_xlat(adict)
print translate('abacacb')
                

如果老板让处理单词的替代(正则中单词:r'\b\S+\b' ):
rx = re.compile(r'\b%s\b' % r'\b|\b'.join(map(re.escape,adict))) #单词版本

如果用函数,这两个版本得重复代码,为了追求专业和优秀,就编码一次!
你说函数传入rx?还是传入compile的内容?oh,天啊,还得在函数外定义些玩意,不够优秀。
alex说,可以用class,以后想要rx就重载make_rx()。
import re

class make_xlat:
    def __init__(self,*args,**kwds):
        self.adict = dict(*args,**kwds)
        self.rx = self.make_rx()
    def make_rx(self):
        return re.compile('|'.join(map(re.escape,self.adict)))
    def one_xlat(self,match):
        return self.adict[match.group(0)]
    def __call__(self,text):
        return self.rx.sub(self.one_xlat,text)

#重载!
class make_xlat_by_whole_words(make_xlat):
    def make_rx(self):
        return re.compile(r'\b%s\b' % r'\b|\b'.join(map(re.escape,self.adict)))


adict = {"a":"1","b":"2","xyz":"456"}

translate = make_xlat(adict)
translate_by_whole_words = make_xlat_by_whole_words(adict)

print translate('aba xyz cacb')
print translate_by_whole_words('aba xyz cacb')

''' 结果:            
>>> 
121 456 c1c2
aba 456 cacb
>>>
'''

Ps:本节重新洗脑了:闭包工厂的思想。同时给我的大脑,加入一个神经发射:当代码重复的时候,就不美丽了,改用class以及重载了。

拓展阅读:
python正则表达式学习 百变贝贝

检查字符串中的结束标记

我需要先介绍下 itertools.imap(选自Python API):
def imap(function, *iterables):
    # imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000
    iterables = map(iter, iterables)
    while True:
        args = [next(it) for it in iterables]
        if function is None:
            yield tuple(args)
        else:
            yield function(*args)
1、先把参数都变成iter对象,iter是个funciton
2、循环调用func来处理iter对象
3、如果看不懂yield,请看拓展阅读第二篇

检查字符串中的结束标记:
Ps:s.endswith 是个function
import itertools,os

def anyTrue(predicate,sequence):
    return True in itertools.imap(predicate,sequence)
def endswith(s,*endings):
    return anyTrue(s.endswith,endings)

for f in os.listdir('.'):
    if endswith(f,'.jpg','.png','.jepg'):
        print f
'''
>>> 
psu.jpg
QQ图片20130927105447.jpg
>>> 
'''

本节还引入了一个概念:被绑定办法(Bound Method)
L = ['a','b','c']
x = L.append
x('d')
print L
这里的x('d') == L.append('d'),x也就是L的一个被绑定办法
这么操作,x是List类型的一个被绑定方法:
x = List.append
x(L,'d') == L.append('d')


拓展阅读:
iter API
Python yield 使用浅析(第二次介绍了)

使用Unicode来处理国际化文本

为什么用utf8,因为它通用:
german_ae = unicode('\xc3\xa4','utf8')
print german_ae
'''
>>> 
ä
>>>
'''
实际上,如果不转换的话,'\xc3\xa4'它就既不是unicode,又不是ascii(高位为1)。python拒绝猜测,所以会报错。

这里也是接触到了几条Python原则:
1、在模糊面前拒绝猜测
2、在IO动作的关口做转换
好吧,在任何一个Python交互式shell输入import this:
>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>> 


在Unicode和普通字符串之间转换

这里放下预言:将来某一天一定会被这个Unicode和str搞死的。

拓展阅读:

str和unicode解析(这是一段有趣的对话,明白encode和decode的真正意义)


在标准输出中打印Unicode字符

pass

对Unicode数据编码并用于XML和HTML

pass

让某些字符串大小写不敏感

pass


将HTML文档转化为文本显示到UNIX终端上

tty是终端设备的统称,isatty应该是is attached tty?:
if sys.stdout.isatty():
    # You're running in a real terminal
else:
    # You're being piped or redirected


拓展阅读:
Linux中tty、pty、pts的概念区别 - 小苗 - 51CTO技术博客
python - How do I detect whether sys.stdout is attached to terminal or not? - Stack Overflow

formatter的相关资料


你可能感兴趣的:(Python)