<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-38514629</id><updated>2011-04-22T03:48:10.164+08:00</updated><category term='Python'/><title type='text'>拒绝懒惰的家</title><subtitle type='html'>滴水穿石,磨杵成针</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default?start-index=101&amp;max-results=100'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>125</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-38514629.post-179272434887531560</id><published>2007-11-30T10:18:00.000+08:00</published><updated>2007-11-30T10:19:00.448+08:00</updated><title type='text'>Python Cookbook 4.13 从字典中提取子集</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;我们需要从一个含有大量数据的字典中获取指定键集合的子集.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果需要保持原字典的完整性,可以这样写:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def sub_dict(somedict, somekeys, default=None):    &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return dict([ (k, somedict.get(k, default)) for k in somekeys ])&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果想从原有字典中去除提取的子集,可以这样写:&lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;def sub_dict_remove(somedict, somekeys, default=None):    &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return dict([ (k, somedict.pop(k, default)) for k in somekeys ])&lt;/span&gt;&lt;br&gt;&lt;br&gt;下面是两个例子:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; d = {&amp;#39;a&amp;#39;: 5, &amp;#39;b&amp;#39;: 6, &amp;#39;c&amp;#39;: 7} &lt;br&gt;&amp;gt;&amp;gt;&amp;gt; print sub_dict(d, &amp;#39;ab&amp;#39;), d&lt;br&gt;&lt;b&gt;{&amp;#39;a&amp;#39;: 5, &amp;#39;b&amp;#39;: 6} {&amp;#39;a&amp;#39;: 5, &amp;#39;b&amp;#39;: 6, &amp;#39;c&amp;#39;: 7}&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; print sub_dict_remove(d, &amp;#39;ab&amp;#39;), d&lt;br&gt;&lt;b&gt;{&amp;#39;a&amp;#39;: 5, &amp;#39;b&amp;#39;: 6} {&amp;#39;c&amp;#39;: 7} &lt;/b&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;在Python中,有很多地方都会用到字典,比如表示数据库的行,主键和组合键,模板解析时的变量命名空间等.所以,我们经常会遇到需要基于一个字典来创建另一个.原来的字典包含有大量数据,而我们只需要其中的一部分.在大多数情况下,需要保持原数据不变,在某些情况下,则需要去除提取的数据.本节中讨论了两种情况的解决方案.两种方法的不同之处在于使用get来保持原数据不变 ,使用pop来去除提取数据.&lt;br&gt;如果有些情况下,在somedict字典中不包含somekey中的键key,本节的方法依然会有一个返回值,它使用了默认值(在函数声明的地方写的是None).所以,结果并不一定完全是somedict的子集.这样的需求在我自己的应用中是最多的.&lt;br&gt;也许你需要获得一个&amp;quot;键不存在&amp;quot;的异常,用于提示自己程序中可能有一个bug,它说明somekey中的有些key不是somedict中的键值.要注意: &amp;quot;错误永远不应默默的溜掉,除非明确的使用沉默&amp;quot;,这是Python之禅的一句.所以,如果键不存在在你的应用程序中是一个错误,你需要立刻获得异常来提示用户,你可以将上面的代码稍微修改一下:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def sub_dict_strict(somedict, somekeys):&lt;br&gt;    return dict([ (k, somedict[k]) for k in somekeys ]) &lt;br&gt;def sub_dict_remove_strict(somedict, somekeys):&lt;br&gt;    return dict([ (k, somedict.pop(k)) for k in somekeys ])&lt;/pre&gt;看,这个代码比以前的还要简单,这说明Python喜欢在不确定的情况下抛出异常!&lt;br&gt;&lt;br&gt;或者,你需要忽略在somedict中不存在的key,可以这样修改:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; def sub_dict_select(somedict, somekeys):&lt;br&gt;    return dict([ (k, somedict[k]) for k in somekeys if k in somedict])&lt;br&gt;def sub_dict_remove_select(somedict, somekeys):&lt;br&gt;    return dict([ (k, somedict.pop(k)) for k in somekeys if k in somedict]) &lt;/pre&gt;在递推式中的if语句实现了我们的需求,排除了不存在的key.&lt;br&gt;在Python2.4以后,你可以使用代码生成器,而不是递推式.仅仅把代码从dict([...])改为dict(...)即可.&lt;br&gt;&lt;br&gt;关于Python之禅,使用&lt;span style="font-weight: bold;"&gt;import this&lt;/span&gt;即可.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-179272434887531560?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/179272434887531560/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=179272434887531560' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/179272434887531560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/179272434887531560'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/11/python-cookbook-413.html' title='Python Cookbook 4.13 从字典中提取子集'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4216393865215666818</id><published>2007-09-24T12:20:00.001+08:00</published><updated>2007-09-24T12:20:11.212+08:00</updated><title type='text'>Python Cookbook 4.12 通过键,值交替的列表创建字典</title><content type='html'>需求:&lt;br&gt;&lt;br&gt;你需要通过一个键,值对交替出现的列表创建字典.&lt;br&gt;&lt;br&gt;讨论:&lt;br&gt;&lt;br&gt;内建的dict类型提供了很多创建字典的方式,可是没有提供本节需求的解决方法,我们需要自己写函数来实现,一种方式是使用zip函数:&lt;br&gt;&lt;pre&gt;def dictFromList(keysAndValues):&lt;br&gt;    return dict(zip(keysAndValues[::2], keysAndValues[1::2])) &lt;/pre&gt;另一种更一般的方式,可以适用与任何可迭代的对象,它将一个列表传递给两个迭代器,这是一个比较通用和迅速的方法:&lt;br&gt;&lt;br&gt;def pairwise(iterable):&lt;br&gt;&amp;nbsp; &amp;nbsp; itnext = iter(iterable).next&lt;br&gt;&amp;nbsp; &amp;nbsp; while True:        &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield itnext( ), itnext( )&lt;br&gt;&lt;br&gt;def dictFromSequence(seq):    &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return dict(pairwise(seq))&lt;br&gt;&lt;br&gt;定以pairwise也可以让其它的函数来使用它,比如mydict.update(pairwise(seq)).&lt;br&gt;上面的两种方面其实内在都使用了同样的构造字典的方式:在调用dict()的时候传递(key,value)的序列,不同之处是怎样构造这个值对序列.&lt;br&gt;dictFromList构造了键值对的列表,它使用了zip函数,使用了两个列表切片,一个是奇数, 一个是偶数.这样是可以工作的,不过有一个问题,就是参数必须是支持切皮的类型比如list,tuple,str等,而且,由于在内存里面使用了临时列表,当参数是很长的列表时,这样做会影响效率.&lt;br&gt;dictFromSequence和上面的方法不同,它将构造键值对的任务交给了pairwise函数.pairwise保证了任何可迭代的对象都可以工作,除了list,tuple和str外,还包括文件,字典等等.另外,pairwise一次只处理一对,并不使用临时队列,当输入队列很长的时候能改善效率. &lt;br&gt;pairwise的实现很有意思.在最开始的时候,它使用iter方法将参数构造为一个迭代器,并将next方法绑定给本地变量itnext,这样做看起来很奇怪,但这是Python中常用的方法:如果你使用一个对象,而且要循环调用这个对象的方法,你可以绑定它的方法,然后使用本地变量来表示那个方法.pairwise和下面这个写法的函数工作的结果是一样的,下面这个代码的写法在其它语言中是比较常见的:&lt;br&gt;&lt;br&gt;def pairwise_slow(iterable): &lt;br&gt;&amp;nbsp; &amp;nbsp; it = iter(iterable)&lt;br&gt;&amp;nbsp; &amp;nbsp; while True:&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; yield it.next( ), it.next( )&lt;br&gt;&lt;br&gt;实际上,pairwise_slow版本的代码并不比pairwise简单多少,却比pairwise慢60%.我们建议程序员使用更Python的方式来写代码.不仅更简单,效率也会更高.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4216393865215666818?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4216393865215666818/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4216393865215666818' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4216393865215666818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4216393865215666818'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/09/python-cookbook-412.html' title='Python Cookbook 4.12 通过键,值交替的列表创建字典'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-5805264128684974641</id><published>2007-09-19T18:04:00.000+08:00</published><updated>2007-09-19T18:05:01.310+08:00</updated><title type='text'>Python Cookbook 4.11 快速构建字典</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你想创建一个字典,它的键值都是字符串,而且你不希望一个个的添加它们.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;一旦你开始使用Python,你会发现需要使用很多很多的字典,当键都是字符串的时候,可以使用dict的命名参数语法来创建:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; data = dict(red=1, green=2, blue=3)&lt;/span&gt;&lt;br&gt;&lt;br&gt;它比下面这个等效的写法简洁许多:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;data = {&amp;#39;red&amp;#39;: 1, &amp;#39;green&amp;#39;: 2, &amp;#39;blue&amp;#39;: 3}&lt;/span&gt;&lt;br&gt;&lt;br&gt;创建字典比较有效的方法就是使用dict函数,它比自己使用括号, 分号的语法来创建字典便捷许多.使用dict,可以避免使用过多的引号,只要键的名称个Python的默认保留字不同.你不能使用类似&amp;#39;12ab&amp;#39;或者&amp;#39;for&amp;#39;,因为&amp;#39;12ab&amp;#39;不是以字母开头,而&amp;#39;for&amp;#39;是Python的保留字.&lt;br&gt;在Python中,用大括号来定义字典是唯一使用大括号的地方:假如你不喜欢使用大括号,或者键盘布局中它很难够到(意大利的键盘就是这样!),你可以使用dict()来代替{ }构造空字典. &lt;br&gt;使用dict还有别的好处,调用dict(d)可以返回已有字典的一个副本,就像调用d.copy()一样,不过,使用dict还有更多的好处,即使d是(key,value)形式的列表也能工作.一个常见的字典构造语法是:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;d = dict(zip(the_keys, the_values))&lt;/pre&gt;其中the_keys是一个包含key的列表,the_values是和它对应的value的列表,内建函数zip返回一个(key,value)形式的列表, dict函数可以接收这样的列表为参数来构造一个字典.如果列表很长,比使用itertools模块要快一些:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;import itertools&lt;br&gt;d = dict(itertools.izip(the_keys, the_values))&lt;/pre&gt;内建的zip方法在内存中构造一个列表,而izip一次只使用一个值对.在我的机器上,对于10,000的数字,后面的方法大约比前面的方法快两倍. &lt;br&gt;在调用dict的时候,你既可以使用位置参数,也可以使用命名参数(如果二者冲突,以命名参数为准),比如,你需要设置最开始说明的不能做为命名参数的键:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;d = dict({&amp;#39;12ba&amp;#39;:49, &amp;#39;for&amp;#39;: 23}, rof=41, fro=97, orf=42)&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果你想创建一个字典,其中每个键所对应的值是一样的, 使用dict.fromkeys(keys,value)(如果没有value,默认是None),比如,我们创建一个统计ascii码出现频率的字典:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import string &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;count_by_letter = dict.fromkeys(string.ascii_lowercase, 0)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明: &lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;fromkeys(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dict.fromkeys(S[,v]) -&amp;gt; New dict with keys from S and values equal to v.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; v defaults to None.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-5805264128684974641?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/5805264128684974641/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=5805264128684974641' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5805264128684974641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5805264128684974641'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/09/python-cookbook-411.html' title='Python Cookbook 4.11 快速构建字典'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-3636062651341155045</id><published>2007-09-18T09:36:00.001+08:00</published><updated>2007-09-18T09:36:33.684+08:00</updated><title type='text'>Python Cookbook 4.19 向字典中添加项</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要使用字典d,并使用d[k]的值,如果d[k]不存在,给它添加新值.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;这就是字典的setdefault方法的功能.比如我们要构造一个单词页码对照表,字典中的单词和它所在的页号一一对应.在代码中关键的部分如下:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; def addword(theIndex, word, pagenumber):&lt;br&gt;    theIndex.setdefault(word, [  ]).append(pagenumber)&lt;/pre&gt;这段代码和下面的冗长的代码作用相同:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def addword(theIndex, word, pagenumber):&lt;br&gt;    if word in theIndex: &lt;br&gt;        theIndex[word].append(pagenumber)&lt;br&gt;    else:&lt;br&gt;        theIndex[word] = [pagenumber]&lt;/pre&gt;或者:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def addword(theIndex, word, pagenumber):&lt;br&gt;    try:&lt;br&gt;        theIndex[word].append(pagenumber) &lt;br&gt;    except KeyError:&lt;br&gt;        theIndex[word] = [pagenumber]&lt;/pre&gt;所以使用setdefault来简化代码吧.&lt;br&gt;对于字典d,d.setdefault(k,v)和d.get(k,v)十分相似.它们之间基本的不同之处在于,假如k不是d中的一部分,setdefault会执行d[k]=v,然后再返回v,(get只返回v,而不会改变d的值).如果你即希望能像get一样取得字典中的值,又希望能适当的改变它,就使用setdefault. &lt;br&gt;对于d的value值是list的情况,setdefault显得特别有用.如本节演示的那样,最常用的写法就是:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;somedict.setdefault(somekey, [  ]).append(somevalue)&lt;/pre&gt;对于不可修改值的情况,setdefault不是那么有用了,比如数字.如果你仅仅想统计数字的个数,比如单词数目,正确的方式是使用get,而不是setdefault: &lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;theIndex[word] = theIndex.get(word, 0) + 1&lt;/pre&gt;因为你必然要重新绑定theIndex[word]变量(因为它是不可修改的),但对于我们的单词页码表的例子,你可不能像下面这样写:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def addword(theIndex, word, pagenumber): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; &amp;nbsp; theIndex[word] = theIndex.get(word, [  ]) + [pagenumber]&lt;/span&gt;&lt;br&gt;&lt;br&gt;最后一个版本的代码在每次执行的时候,使用了3个list,一个是[]做为参数,另一个包含pagenumber,最后一个包含N+1个元素.是由上面两个连接而成的.如此大量的使用列表必然会影响程序的效率.比如 ,在我的机器上,我统计了4个单词,每个都在1000页中的每页出现一次.以引用中的第一个版本为基准,try/except方法比它快10%,setdefault方法比它慢20%,在大多数的情况下,这点差异是可以忽略的.而get方法比它慢4倍,这样的效率差别是不可忽略的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; setdefault(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; D.setdefault(k[,d]) -&amp;gt; D.get(k,d), also set D[k]=d if k not in D&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-3636062651341155045?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/3636062651341155045/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=3636062651341155045' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3636062651341155045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3636062651341155045'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/09/python-cookbook-419.html' title='Python Cookbook 4.19 向字典中添加项'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-5005877984861469034</id><published>2007-09-06T17:20:00.001+08:00</published><updated>2007-09-06T17:20:33.367+08:00</updated><title type='text'>算法学习: 判读四点是否构成矩形</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;给定4个点的坐标,判断这4点是否构成一个矩形.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;这是我遇到的一个笔试题,在这里给出一个自己想的算法:&lt;br&gt;&lt;br&gt;在四个点中取第一点为基点,分别算出到其它三点的距离.如果这三个值满足勾股定理,则:&lt;br&gt;1.该四点构成矩形&lt;br&gt; 2.该四点构成平行四边形&lt;br&gt;&lt;br&gt;对于第二种情况,再进行判读,如果其中心与重心重回,即四点在一个圆上,则该四点构成矩形.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;程序如下:&lt;/span&gt;&lt;br&gt;&lt;br&gt;def IsSquire(*arg):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; x1,y1 = arg[0]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; x2,y2 = arg[1]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; x3,y3 = arg[2]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; x4,y4 = arg[3] &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; line1 = (x1-x2)**2 + (y1-y2)**2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; line2 = (x1-x3)**2 + (y1-y3)**2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; line3 = (x1-x4)**2 + (y1-y4)**2&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (abs(line1-line2))==line3 or (line1+line2)==line3:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x0 = (x1+x2+x3+x4)/4&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; y0 = (y1+y2+y3+y4)/4 &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (x1-x0)**2+(y1-y0)**2 == (x2-x0)**2+(y2-y0)**2 == (x3-x0)**2+(y3-y0)**2 == (x4-x0)**2+(y4-y0)**2:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return True&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return False&lt;br&gt;if __name__==&amp;quot;__main__&amp;quot;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print IsSquire((0,0),(1,0),(0,1),(-1,1)) &lt;br&gt;&lt;br&gt;其实更简单一些的方法是判断中心是否在较长的边上即可,不过那样代码要些很多if.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-5005877984861469034?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/5005877984861469034/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=5005877984861469034' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5005877984861469034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5005877984861469034'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/09/blog-post.html' title='算法学习: 判读四点是否构成矩形'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-82384070817859958</id><published>2007-09-05T14:51:00.000+08:00</published><updated>2007-09-05T14:52:00.768+08:00</updated><title type='text'>Python Cookbook 4.9 从字典中获得值</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要从一个字典中获得值,而且不用处理异常情况,比如该值不存在.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;dict的get方法就能满足需求.比如你有一个字典d = {&amp;#39;key&amp;#39;:&amp;#39;value&amp;#39;}.为了获得key所对应的值,并不考虑异常情况,使用: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print d.get(&amp;#39;key&amp;#39;, &amp;#39;not found&amp;#39;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果你想用完该数据后就删除它,请使用dict.pop(它进行get和remove操作),而不是dict.get(它不会执行remove操作).&lt;br&gt;要想获得一个数值,而且不希望遇到异常,就是用get方法.&lt;br&gt;如果你使用索引值来访问d[x],如果x对应的值在d中不存在,你就会获得KeyError异常,这个很正常,如果你需要的值在dict中不存在, 它就会以异常的方式提示你出错了.有时你只是想试探一下,看x对应的值在字典中是否存在,这样的情况下,不要使用in语句:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if &amp;#39;key&amp;#39; in d:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; &amp;nbsp; print d[&amp;#39;key&amp;#39;] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; &amp;nbsp; print &amp;#39;not found&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;使用try/except语法:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;try:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; &amp;nbsp; print d[&amp;#39;key&amp;#39;] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;except KeyError:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; &amp;nbsp; print &amp;#39;not found&amp;#39;&lt;/span&gt;&lt;br&gt;&lt;br&gt;和上面的处理不同,如果你使用get(x)语法,不会有异常抛出:如果x对应的值存在,将返回它,如果不存在, 会返回None.如果你不希望它返回None,可以使用d.get(x,somethingelse),在这种情况下,如果x对应的值不存在,不会返回None,而是somethingelse.&lt;br&gt;get是一个非常简单的方法,而且Python的文档中也描述的很详细,但是还有很多人都不知道它.与此类似,pop是另一个函数,它的大部分用法都和get相同.唯一不同的是,pop可以返回异常,当x不是d中的一个key是,d.pop(x)会抛出KeyError异常,如果你希望它的用法和get完全一样, 使用d.pop(x,None).&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;get(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; D.get(k[,d]) -&amp;gt; D[k] if k in D, else d.&amp;nbsp; d defaults to None. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;pop(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; D.pop(k[,d]) -&amp;gt; v, remove specified key and return the corresponding value&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If key is not found, d is returned if given, otherwise KeyError is raised &lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-82384070817859958?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/82384070817859958/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=82384070817859958' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/82384070817859958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/82384070817859958'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/09/python-cookbook-49.html' title='Python Cookbook 4.9 从字典中获得值'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-8840699632697860428</id><published>2007-09-03T12:19:00.001+08:00</published><updated>2007-09-03T12:19:59.565+08:00</updated><title type='text'>Python Cookbook 4.8 转置2维数组</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要转置一个二维数组,将行列互换.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要确保该数组的行列数都是相同的.比如:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] &lt;/span&gt;&lt;br&gt;&lt;br&gt;列表递推式提供了一个简便的矩阵转置的方法:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print [[r[col] for r in arr] for col in range(len(arr[0]))] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;b style="color: rgb(204, 0, 0);"&gt;[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]&lt;/b&gt;&lt;br&gt;&lt;br&gt;另一个更快和高级一些的方法,可以使用zip函数:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print map(list, zip(*arr)) &lt;/span&gt;&lt;br&gt;&lt;br&gt;本节提供了关于矩阵转置的两个方法,一个比较清晰简单,另一个比较快速但有些隐晦.&lt;br&gt;有时候,数据到来的时候使用错误的方式,比如,你使用微软的ADO接口访问数据库,由于Python和MS在语言实现上的差别. Getrows方法在Python中可能返回的是列值,和方法的名称不同.本节给的出的方法就是这个问题常见的解决方案,一个更清晰,一个更快速.&lt;br&gt;在列表递推式版本中,内层递推式表示选则什么(行),外层递推式表示选择者(列).这个过程完成后就实现了转置.&lt;br&gt;在zip版本中,我们使用*arr语法将一维数组传递给zip做为参数,接着,zip返回一个元组做为结果.然后我们对每一个元组使用list方法,产生了列表的列表(即矩阵).因为我们没有直接将zip的结果表示为list, 所以我们可以我们可以使用itertools.izip来稍微的提高效率(因为izip并没有将数据在 内存中组织为列表).&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import itertools &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print map(list, itertools.izip(*arr))&lt;/span&gt;&lt;br&gt;&lt;br&gt;但是,在特定的情况下,上面的方法对效率的微弱提升不能弥补对复杂度的增加.&lt;br&gt;关于*args和**kwds语法:&lt;br&gt;*args(实际上,*号后面跟着变量名)语法在Python中表示传递任意的位置变量,当你使用这个语法的时候(比如,你在定义函数时使用),Python将这个变量和一个元组绑定,并保留所有的位置信息, 而不是具体的变量.当你使用这个方法传递参数时,变量可以是任意的可迭代对象(其实可以是任何表达式,只要返回值是迭代器).&lt;br&gt;**kwds语法在Python中用于接收命名参数.当你用这个方式传递参数时,Python将变量和一个dict绑定,保留所有命名参数,而不是具体的变量值.当你传递参数时,变量必须是dict类型(或者是返回值为dict类型的表达式).&lt;br&gt;&lt;br&gt;如果你要转置很大的数组,使用Numeric Python或其它第三方包,它们定义了很多方法,足够让你头晕的. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;zip(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; zip(seq1 [, seq2 [...]]) -&amp;gt; [(seq1[0], seq2[0] ...), (...)]&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return a list of tuples, where each tuple contains the i-th element &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; from each of the argument sequences.&amp;nbsp; The returned list is truncated&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; in length to the length of the shortest argument sequence.&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-8840699632697860428?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/8840699632697860428/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=8840699632697860428' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8840699632697860428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8840699632697860428'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/09/python-cookbook-48-2.html' title='Python Cookbook 4.8 转置2维数组'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-1517175520151585168</id><published>2007-08-31T14:35:00.001+08:00</published><updated>2007-08-31T14:35:28.763+08:00</updated><title type='text'>Python Cookbook 4.7 在2维列表中删除或重排某些列</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你有一个二维列表,需要重新获得一个列表,其中行不变,而将某些列重排或者删除.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;使用列表递推式可以处理这个问题,比如你有如下的列表:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;listOfRows = [ [1,2,3,4], [5,6,7,8], [9,10,11,12] ] &lt;/span&gt;&lt;br&gt;&lt;br&gt;现在你需要将第二列删除,并将第四列和第三列互换位置,用一个列表递推式就能出色的完成任务:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;newList = [ [row[0], row[3], row[2]] for row in listOfRows ]&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;结果如下:&lt;/span&gt; &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;[[1, 4, 3], [5, 8, 7], [9, 12, 11]]&lt;/span&gt;&lt;br&gt;&lt;br&gt;另外的办法,稍微复杂一些,是使用临时的列表来保存要调整的位置:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;newList = [ [row[ci] for ci in (0, 3, 2)] for row in listofRows ] &lt;/span&gt;&lt;br&gt;&lt;br&gt;我经常使用列表的列表来表示二维数组,而在处理这类问题的过程中经常遇到列的处理,比如重排某些列,忽略其中的一些数值等.使用列表递推式来处理这一类问题看起来不是那么显然.&lt;br&gt;列表递推式创建一个新列表,而不是改变原来的.但是即使你需要修改现有的列表,使用列表递推式然后赋值给现有列表也是很好的方法.比如,你想修改listOfRows,就按照本节的需求,你可能这样写:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; listOfRows[:] = [ [row[0], row[3], row[2]] for row in listOfRows ]&lt;/span&gt;&lt;br&gt;&lt;br&gt;但是请注意,遇到这样的问题,请是用本节给出的第二个列子的办法,用一个临时列表保存列的位置,而不是硬编码.也许你不喜欢将两个递推式嵌套起来,但是它会更安全一些.如果你使用这种方法,还能得到附加的好处,因为增强的灵活性,你可以将它封装成一个函数,将想要调整的顺序做为参数传递进去:&lt;br&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def pick_and_reorder_columns(listofRows, column_indexes):     &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [ [row[ci] for ci in column_indexes] for row in listofRows ] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;columns = 0, 3, 2 &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;newListOfPandas = pick_and_reorder_columns(oldListOfPandas, columns) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;newListOfCats = pick_and_reorder_columns(oldListOfCats, columns)&lt;/span&gt;&lt;br&gt;&lt;br&gt;上面的代码和前面的 一样,调整了列表中列的顺序,但是它操作的是两个列表.&lt;br&gt;最后要注意的,有些人喜欢将列表递推式中的变量部分替换成函数返回值,而不是直接使用,比如在: &lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;[row[ci] for ci in column_indexes]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; 可以使用map函数,用__getitem__来代替[],所以可以这样写:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;map(row._ _getitem_ _, column_indexes)&lt;/span&gt;&lt;br&gt;&lt;br&gt;取决于你的Python版本,也许map版的会更快一些.不过我坚持认为最简单的列表递推式是最好的 .&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-1517175520151585168?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/1517175520151585168/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=1517175520151585168' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1517175520151585168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1517175520151585168'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-47-2.html' title='Python Cookbook 4.7 在2维列表中删除或重排某些列'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-3943322462536253504</id><published>2007-08-29T10:12:00.001+08:00</published><updated>2007-08-29T10:12:06.876+08:00</updated><title type='text'>Python Cookbook 4.6 将嵌套列表转换为单列表</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;有些列表的元素可能还是一个列表,而这样的嵌套可能持续下去.你需要遍历列表的每一个元素,并将嵌套的列表元素转换为单列表(及列表中不存在列表).&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;我们需要首先讨论一下什么元素是&amp;quot;子列表&amp;quot;,并要将它扩展到什么标准.简单来说 ,我们需要提供一个断言来说明什么样的元素是需要我们扩展的.(断言是一个函数,可以对于任何对象调用,它返回它的真实性,在这里,true表示可以扩展,false表示不能).默认的情况,我们可以说列表(list)和元素是可以扩展(tuple)的,而其它的类型不可以.然后写下下面的代码:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def list_or_tuple(x):&lt;br&gt;    return isinstance(x, (list, tuple)) &lt;br&gt;def flatten(sequence, to_expand=list_or_tuple):&lt;br&gt;    for item in sequence:&lt;br&gt;        if to_expand(item):&lt;br&gt;            for subitem in flatten(item, to_expand):&lt;br&gt;                yield subitem&lt;br&gt;        else:&lt;br&gt;             yield item&lt;/pre&gt;在嵌套列表中处理,或者说,在一个树中遍历叶子节点,是很多应用程序都会遇到的问题.你从一个嵌套结构开始,而只关心里面的元素,并不关心它的结构,比如:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;for x in flatten([1, 2, [3, [  ], 4, [5, 6], 7, [8,], ], 9]):&lt;br&gt;    print x,&lt;/pre&gt; 输出&lt;tt&gt;&lt;b&gt;1 2 3 4 5 6 7 8 9&lt;/b&gt;&lt;/tt&gt;.&lt;br&gt;&lt;br&gt;在这类问题中,核心问题是需要知道什么元素是需要扩展的,或者对什么元素使用yield,并不是想像中的那么明显.所以我避开了这个问题,将它交给一个代理函数,有用户决定什么类型是需要扩展的,默认只处理列表类型和元组类型.&lt;br&gt;在flatten模块中,我们需要再写一个断言函数,因为用户可能希望扩展一切具有迭代特性的对象,当然除了字符串,因为它是不可修改的,而且本身就是常量,而不是子列表. &lt;br&gt;为了判断一个对象是否具有可迭代属性,调用它的iter方法就可以了,如果返回TypeError异常,就说明它是不可迭代的.判读一个对象是不是字符串类型,看看它是不是basestring的子类就可以了.所以,这个断言并不难写:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def nonstring_iterable(obj):&lt;br&gt;    try: iter(obj)&lt;br&gt;    except TypeError: return False &lt;br&gt;    else: return not isinstance(obj, basestring)&lt;/pre&gt;现在调用者可以使用nonstring_iterable,如果它希望将任何可迭代对象扩展的话.不过,最好不要把nonstring_iterable做为断言的默认值,因为它会比list_or_tuple慢3倍.&lt;br&gt;我们也可以写一个非递归的版本.这样可以使你避免达到Python递归的深度上限.这个上限一般是几千层.替代递归的方法就是建立一个后入先出的堆栈 (LIFO).在这里,我们可以使用iterator的列表来实现:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def flatten(sequence, to_expand=list_or_tuple):&lt;br&gt;    iterators = [ iter(sequence) ]&lt;br&gt;    while iterators:&lt;br&gt;        # loop on the currently most-nested (last) iterator &lt;br&gt;        for item in iterators[-1]:&lt;br&gt;            if to_expand(item):&lt;br&gt;                # subsequence found, go loop on iterator on subsequence&lt;br&gt;                iterators.append(iter(item))&lt;br&gt;                break &lt;br&gt;            else:&lt;br&gt;                yield item&lt;br&gt;        else:&lt;br&gt;            # most-nested iterator exhausted, go back, loop on its parent&lt;br&gt;            iterators.pop( )&lt;/pre&gt;if语句的子句对每一个传递进的item进行操作,在那个子句中我们将item的迭代器放入iterators中,然后跳出for循环,回到外层的while循环, 它会对我们添加进的迭代器进行新的for循环.if语句的else语句是将任何不需要扩展的元素进行yield操作.&lt;br&gt;for语句的else语句在没有调用break且for执行完毕后运行,也就是说,当前列表已经遍历完毕.所以我们删除它的迭代器,回到while循环.while循环会开始新的循环,或者中止.实际上,我们记录了迭代的状态.&lt;br&gt;上面的非递归代码也适用于一般的简单递归问题.如果你认为递归比非递归要快,那么你要失望了,根据我自己的经验,非递归解法要比递归解法慢10%,这是在一系列例子运行后总结的结果. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;iter(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; iter(collection) -&amp;gt; iterator&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; iter(callable, sentinel) -&amp;gt; iterator&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Get an iterator from an object.&amp;nbsp; In the first form, the argument must &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; supply its own iterator, or be a sequence.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; In the second form, the callable is called until it returns the sentinel.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-3943322462536253504?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/3943322462536253504/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=3943322462536253504' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3943322462536253504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3943322462536253504'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-46.html' title='Python Cookbook 4.6 将嵌套列表转换为单列表'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4831900286938118151</id><published>2007-08-28T13:48:00.001+08:00</published><updated>2007-08-28T13:53:39.845+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 4.5 创建多维列表,避免元素共享引用</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要简历多维列表,并且要避免元素引用共享.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;为了创建列表且避免引用共享,使用列表递推式,比如,建立一个5*10的数组,并初始化为0:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;multilist = [[0 for col in range(5)] for row in range(10)] &lt;/span&gt;&lt;br&gt;&lt;br&gt;当新接触Python时,对它的用列表乘法来初始化数组很兴奋,那真是一个聪明的语法:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; alist = [0] * 5&lt;/span&gt;&lt;br&gt;&lt;br&gt;这样来获得包含5个元素的数组很方便.&lt;br&gt;很自然,也会想到2维数组可以这样写:&lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; multi = [[0] * 5] * 3&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; print multi&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]&lt;/span&gt;&lt;br&gt;&lt;br&gt;这样写看起来有效,但是很快新手们会遇到问题:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; multi[0][0] = &amp;#39;oops!&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;gt;&amp;gt;&amp;gt; print multi&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;[[&amp;#39;oops!&amp;#39;, 0, 0, 0, 0], [&amp;#39;oops!&amp;#39;, 0, 0, 0, 0], [&amp;#39;oops!&amp;#39;, 0, 0, 0, 0]]&lt;/span&gt;&lt;br&gt;&lt;br&gt;这个问题曾经困扰了很多人, 尤其是新手.为了说明问题,我们最好首先把它分解成两部分:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; row = [0] * 5 # a list with five references to 0&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; multi = [row] * 3 # a list with three references to the row object &lt;/span&gt;&lt;br&gt;&lt;br&gt;这个分解说明了问题,它和前面的代码功能是一样的,如果你改变了multi[0][0]的值,也会改变multi[1][0].&lt;br&gt;上面代码后面的注释说明问题,用列表和数字相乘创建新的列表,并且拥有以前列表元素的内容.在这种情况下,创建了row,我们不用关心引用是否被复制,因为引用的是一个数字, 也可以推广到不可修改对象.也就是说,如果引用的对象是一个不可修改对象,那么该对象和该对象的引用就没有什么实质的区别.在第二行 ,我们从row又创建了一个列表,它的里面包含的都是row的应用.因此,multi包含了3个row对象的引用.所以,当row的一个元素修改后,其余的也会表现出来.&lt;br&gt;而列表递推式,就像本节开始给出的代码,避免了这个问题.在进行列表递推式的时候,处于内层的递推式不会进行引用共享.如果你想更深入的讨论这个问题,我们甚至可以说你连内层的递推式也不需要.换句话说,如果我问下面这个语句是不是等价:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; multilist = [[0]*5 for row in range(10)]&lt;/span&gt;&lt;br&gt;&lt;br&gt;那么答案是yes.事实上,使用这种方法,比使用嵌套递推式快两倍,那么为什么我们不推荐使用后面这种方法呢?因为提升速度的绝对值太小了,对你的程序性能影响并不大,而且重要的是,它牺牲了可读性!&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4831900286938118151?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4831900286938118151/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4831900286938118151' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4831900286938118151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4831900286938118151'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-45_28.html' title='Python Cookbook 4.5 创建多维列表,避免元素共享引用'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-5997817538904453340</id><published>2007-08-28T09:53:00.001+08:00</published><updated>2007-08-28T13:53:39.845+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python 学习:单链表的实现</title><content type='html'>要定义一个单链表,首先定义链表元素:Element.&lt;br&gt;它包含3个字段:&lt;br&gt;list:标识自己属于哪一个list&lt;br&gt;datum:改元素的value&lt;br&gt;next:下一个节点的位置&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;class LinkedList(object):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class Element(object):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self,list,datum,next): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._list = list&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._datum = datum&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._next = next&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getDatum(self): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._datum&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; datum = property(&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self:  self.getDatum())&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getNext(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._next&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; next = property(&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self: self.getNext())&lt;/span&gt;&lt;br&gt;&lt;br&gt;Element的构造函数很简单,只是用参数初始化新的节点.&lt;br&gt;&lt;br&gt;接下来,我们定义LinkedList的初始化函数: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._head = None&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._tail = None&lt;/span&gt;&lt;br&gt;&lt;br&gt;这个函数初始化列表的头和尾元素.&lt;br&gt;另,我们也定义一个链表清空函数,用于将链表初始化为空链表:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def purge(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._head = None&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._tail = None &lt;/span&gt;&lt;br&gt;&lt;br&gt;我们为链表类定义3个属性:head,tail和isEmpty,分别表示链表的头,尾和判断链表是否为空.&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getHead(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._head &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; head = property(&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self: self.getHead()) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getTail(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._tail &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; tail = property(&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self: self.getTail()) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def IsEmpty(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._head == None&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; isEmpty = property(&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self: self.IsEmpty())&lt;/span&gt;&lt;br&gt;&lt;br&gt;我们为链表类再定义两个属性,first和last, 用于获得链表的头和尾元素的值.当链表为空时,抛出ContainerEmpty异常:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getFirst(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self._head is None:&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise ContainerEmpty&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._head._datum&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; first = property(&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self:  self.getFirst())&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getLast(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self._tail is None:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise ContainerEmpty&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._tail._datum &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; last = property(&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self: self.getLast  ()) &lt;/span&gt;&lt;br&gt;&lt;br&gt;prepend函数用于将元素插入链表头,这样,插入后的元素变成新的链表头:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def prepend(self,item):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = self.Element (self,item,self._head)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self._head is None:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._tail = tmp &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._head = tmp &lt;/span&gt;&lt;br&gt;&lt;br&gt;append函数用于给链表末尾添加元素.当链表为空时,添加的元素成为链表的头元素,然后,将元素添加到链表的尾部.&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def append(self,item):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = Element(self,item,None)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self._head is None:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._head = tmp&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._tail._next = tmp&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._tail = tmp&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;给链表定义copy函数,它是 一个浅拷贝函数,首先建立一个空链表,然后逐个添加元素:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __copy__(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lst = LinkedList()&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ptr = self._head&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while ptr is not None: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lst.append(ptr._datum)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ptr = ptr._next&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return lst&lt;/span&gt;&lt;br&gt;&lt;br&gt;定义链表的删除函数extract,用于删除链表中的特定元素.首先查找该元素的位置,如果不存在,提示KeyError异常.当元素是头元素时,将其下一个节点变为头元素;当其节点是尾元素时,将上一个节点变成尾元素.然后删除它.&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def extract(self,item):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; prePtr = ptr = self._head&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while ptr is not None and ptr._datum is not item:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; prePtr = ptr&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ptr = ptr._next&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ptr is None:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise KeyError &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ptr == self._head:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._head = ptr._next &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; prePtr._next = ptr._next&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ptr == self._tail:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._tail = prePtr&lt;/span&gt;&lt;br&gt;&lt;br&gt;find函数用于查找指定的元素,当没有找到时,返回None: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def find(self,item):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ptr = self._head&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while ptr is not None and ptr._datum is not item:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ptr = ptr._next&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ptr&lt;/span&gt;&lt;br&gt;&lt;br&gt;至此,一个简单的单链表就已经实现了,可以继续扩展它的功能.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-5997817538904453340?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/5997817538904453340/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=5997817538904453340' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5997817538904453340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5997817538904453340'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python.html' title='Python 学习:单链表的实现'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4886376558505717731</id><published>2007-08-27T13:52:00.001+08:00</published><updated>2007-08-28T13:53:39.845+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python 学习:扩展Python的列表--Array</title><content type='html'>Python默认的List类型可以做为数组来使用,可是它有一些特点:&lt;br&gt;&lt;br&gt;1.允许负索引,这是一般的Array类型所不允许的.&lt;br&gt;2.只能从0开始索引,有时候我们需要从一个特定的数字开始索引.&lt;br&gt;&lt;br&gt;我们首先来构造一个简单的Array类型,它有两个简单的属性:&lt;br&gt;_data:用于保存数据&lt;br&gt;_baseIndex:用于保存起始索引号&lt;br&gt;&lt;br&gt;写下下面的类:&lt;br&gt;&lt;br&gt;class Array(object): &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self,length = 0,baseIndex = 0):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert length &amp;gt;= 0&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._data = [None for x in xrange(length)]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._baseIndex = baseIndex&lt;br&gt;&lt;br&gt;该类可以接收两个参数,一个是初始的长度,另一个是起始的索引数.默认是0 .&lt;br&gt;接下来,我们定义Array的拷贝函数.这样,以后我们就可以这样使用它:&lt;br&gt;&lt;br&gt;import copy&lt;br&gt;a = Array(5)&lt;br&gt;b = copy.copy(a)&lt;br&gt;&lt;br&gt;为了实现这个功能,我们需要定义__copy__函数,这样,在使用copy的时候,就能调用我们的拷贝函数:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __copy__(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = Array(len(self._data),self._baseIndex) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i,item in enumerate(self._data):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result._data[i] = item&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result&lt;br&gt;&lt;br&gt;为了像列表一样,使用[]来访问元素,我们需要定义两个函数:__getattr__和__setattr__,当索引值不存在时,也要报出异常,为了计算出合适的索引,再定义一个getOffset函数:&lt;br&gt;&lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; def getOffset(self,index):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; offset = index - self._baseIndex&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if offset &amp;lt; 0 or offset &amp;gt;= len(self._data):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise IndexError&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return offset&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __getattr__(self,index): &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._data[self.getOffset(index)]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __setattr__(self,index,value):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._data[self.getOffset(index)] = value&lt;br&gt;&lt;br&gt;这样,我们就能像访问列表一样访问Array的元素.&lt;br&gt;&lt;br&gt;同时,为了给用户提供获得Array信息的能力,我们提供了两个属性(property),data和baseIndex,定义属性,可以使用fget和fset访问器: &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getData(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._data&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; data=property(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self: self.getData())&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getBaseIndex(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self._baseIndex&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def setBaseIndex(self,index): &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._baseIndex = index&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; baseIndex=property(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self: self.getBaseIndex(),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fset = lambda self,index: self.setBaseIndex(index))&lt;br&gt;&lt;br&gt;我们为Array定义修改大小的接口.&lt;br&gt;为此,我们首先为Array提供获得长度的接口__len__,然后可以定义fget和fset访问器. &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __len__(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return len(self._data)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def setLenght(self,value):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len(self._data)!=value:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newData = [None for i in xrange(value)]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m = min(len(self._data),value) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in xrange(m):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newData[i] = self._data[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._data = newData&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; length=property(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fget = lambda self: self.__len__(),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fset = lambda self,value:  self.setLenght(value))&lt;br&gt;&lt;br&gt;至此,一个简单的扩展的Array类型就定义完毕了.&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4886376558505717731?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4886376558505717731/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4886376558505717731' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4886376558505717731'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4886376558505717731'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-python-array.html' title='Python 学习:扩展Python的列表--Array'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-417820034992477473</id><published>2007-08-27T11:43:00.001+08:00</published><updated>2007-08-28T13:53:39.846+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 4.4 在序列中遍历它的元素和索引</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要遍历一个序列,同时,你也要知道当前的元素的索引号.(你也许要改变它们的顺序),而Python使用的遍历方式不依赖于索引号.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;使用Python的enumerate可以解决这个问题,比如:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; for index, item in enumerate(sequence):&lt;br&gt;    if item &amp;gt; 23:&lt;br&gt;        sequence[index] = transform(item)&lt;/pre&gt;这比使用索引来访问序列更清晰,可读和快速:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for index in range(len(sequence)):    &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp; if sequence[index] &amp;gt; 23:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; sequence[index] = transform(sequence[index]) &lt;/span&gt;&lt;br&gt;&lt;br&gt;遍历序列是很常见的需求,Python也加强了这方面的处理,你可以很方便的处理这样的需求.换句话说,最Python的使用方法是:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for item in sequence:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp; &amp;nbsp; process(item)&lt;/span&gt;&lt;br&gt;&lt;br&gt;而不是和一些低级语言一样,需要按照元素的索引号来访问数据.&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for index in range(len(sequence)):    &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; process(sequence[index])&lt;/span&gt;&lt;br&gt;&lt;br&gt;直接遍历更清晰,简洁,快速和通用(你可以遍历任何序列,而使用索引只能遍历列表)&lt;br&gt;然而,有些情况下,你需要知道索引值,最常见的用法就是重新为序列元素绑定值.为了满足这个需求,Python提供了内建函数enumerate,这个函数可以接收任何可迭代对象为参数,并返回一个值对(index,item),可以使用下面的for循环来完成: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for index, item in enumerate(sequence):&lt;/span&gt;&lt;br&gt;&lt;br&gt;这样能同时得到索引值和元素.&lt;br&gt;对于列表L,可以使用d=dict(enumerate),这样返回了一个和L等价的字典.其中d[i] is L[i]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt; &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;class enumerate(object)&lt;/span&gt;&lt;br&gt;&amp;nbsp;|&amp;nbsp; enumerate(iterable) -&amp;gt; iterator for index, value of iterable&lt;br&gt;&amp;nbsp;|&lt;br&gt;&amp;nbsp;|&amp;nbsp; Return an enumerate object.&amp;nbsp; iterable must be an other object that supports &lt;br&gt;&amp;nbsp;|&amp;nbsp; iteration.&amp;nbsp; The enumerate object yields pairs containing a count (from&lt;br&gt;&amp;nbsp;|&amp;nbsp; zero) and a value yielded by the iterable argument.&amp;nbsp; enumerate is useful&lt;br&gt;&amp;nbsp;|&amp;nbsp; for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ... &lt;br&gt;&amp;nbsp;|&lt;br&gt;&amp;nbsp;|&amp;nbsp; Methods defined here:&lt;br&gt;&amp;nbsp;|&lt;br&gt;&amp;nbsp;|&amp;nbsp; __getattribute__(...)&lt;br&gt;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x.__getattribute__(&amp;#39;name&amp;#39;) &amp;lt;==&amp;gt; &lt;a href="http://x.name"&gt;x.name&lt;/a&gt;&lt;br&gt;&amp;nbsp;|&lt;br&gt;&amp;nbsp;|&amp;nbsp; __iter__(...)&lt;br&gt;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x.__iter__() &amp;lt;==&amp;gt; iter(x) &lt;br&gt;&amp;nbsp;|&lt;br&gt;&amp;nbsp;|&amp;nbsp; next(...)&lt;br&gt;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x.next() -&amp;gt; the next value, or raise StopIteration&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-417820034992477473?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/417820034992477473/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=417820034992477473' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/417820034992477473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/417820034992477473'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-44.html' title='Python Cookbook 4.4 在序列中遍历它的元素和索引'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4382240179956410253</id><published>2007-08-27T11:26:00.001+08:00</published><updated>2007-08-28T13:53:39.846+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 4.3 返回列表中的元素</title><content type='html'>&lt;br&gt;&lt;br&gt;---------- Forwarded message ----------&lt;br&gt;&lt;span class="gmail_quote"&gt;From: &lt;b class="gmail_sendername"&gt;侯志刚&lt;/b&gt; &amp;lt;&lt;a href="mailto:hzgnpu@gmail.com"&gt;hzgnpu@gmail.com&lt;/a&gt;&amp;gt;&lt;br&gt;Date: 2007-8-27 上午11:25&lt;br&gt;Subject: Python Cookbook  4.3 返回列表中的元素&lt;br&gt;To: &lt;a href="mailto:hzgnpu@gmail.com"&gt;hzgnpu@gmail.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你有列表L和索引i,如果L[i]元素有效,你需要得到它的值,否则,返回默认值v,如果L是一个字典,你可以使用L.get(i,v),但是List没有get方法.&lt;br&gt; &lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;很显然,我们需要自己写一个函数,最简单的就是最有效的:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def list_get(L, i, v=None):&lt;br&gt;    if -len(L) &amp;lt;= i &amp;lt; len(L): return L[i]&lt;br&gt;    else: return v &lt;/pre&gt;本节的函数首先判断i是否是一个有效的索引值,它使用了Python的列表索引规则:合法的索引值处于[-len(L),len(L))区间内.如果大部分的索引值都是有效的,可以尝试使用下面的方法:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def list_get_egfp(L, i, v=None):&lt;br&gt;    try: return L[i]&lt;br&gt;    except IndexError: return v &lt;/pre&gt;然而,除非几乎全部的索引都是有效的,上面的方法可能最多会比本节给出的函数慢4倍.&lt;br&gt;我也尝试了许多不同的方法来实现需求,可是不知道什么原因,总是比list_get慢一些,一般的规则:当你写Python代码时,使用简单而清晰的方法而不是复杂或紧密的代码.这样你的代码往往运行的更快 ,更一直,也会让你的代码更稳定,更易维护.&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4382240179956410253?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4382240179956410253/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4382240179956410253' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4382240179956410253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4382240179956410253'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-43.html' title='Python Cookbook 4.3 返回列表中的元素'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-2800290286498858866</id><published>2007-08-26T16:22:00.001+08:00</published><updated>2007-08-28T13:53:39.846+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 4.2 用递推式构造列表(List Comprehensions)</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要构造一个新的列表,列表中的元素是从一个已知列表中的元素计算而得到的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;比如你要创建一个列表,里面的元素是另一个列表中的元素加23后得到的.使用递推式构造列表是最理想的方法:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; thenewlist = [x + 23 for x in theoldlist]&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果你希望用一个列表中大于5的元素构造一个新的列表,使用递推式也是很方便的:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thenewlist = [x for x in theoldlist if x &amp;gt; 5]&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果你希望将上面的两种情况组合起来,可以使用if表达式, 还可以使用计算式.比如给选中的元素加23,用一句话写成:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thenewlist = [x + 23 for x in theoldlist if x &amp;gt; 5]&lt;/span&gt;&lt;br&gt;&lt;br&gt;优雅,清晰和实用,是Python的核心思想.递推式表现了3者的完美接合.的确,递推式是构造列表的最好方法,有时候,甚至也是修改列表的不错的选择.比如,你需要将列表中大于100的数改成100,可以这样写: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;L[:] = [min(x,100) for x in L]&lt;/span&gt;&lt;br&gt;&lt;br&gt;给列表的完整切片赋值会修改列表的内容,而不是仅仅重新绑定变量名,如果你写成L=...就是重新绑定变量名了.&lt;br&gt;如果你仅仅想对列表进行迭代,最好还是使用循环,而不是递推式,可以参考下一节.&lt;br&gt;如果有另外的内建方法可以完成同样的功能,最好也不要使用迭代式.比如复制列表 ,使用L1 = list(L),不要用:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;L1 = [x for x in L]&lt;/span&gt;&lt;br&gt;&lt;br&gt;另外,如果要对列表中的每一个元素进行函数操作,并将其返回值作为元素使用,请使用map函数,L1 = map(f,L),而不是[f(x) for x in L].不过在大多数情况下,使用递推式是比较方便的.&lt;br&gt;在Python2.4中,如果列表比较长,而且你一次只需要其中的一个元素, 使用生成表达式比较合适.生成表达式的写法和递推式是很类似的,它使用()来区分.在Python2.3中,比如我们要获得列表元素的和,而不是其中的每一个元素,可以这样写:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;total = sum([x + 23 for x in theoldlist if x &amp;gt; 5])&lt;/span&gt;&lt;br&gt;&lt;br&gt;在Python2.4中,可以不要[]:&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;total = sum(x + 23 for x in theoldlist if x &amp;gt; 5)&lt;/span&gt;&lt;br&gt;&lt;br&gt;除了少写一对[],表达式也避免了维护一个列表,节省了内存空间.尤其当列表很长的时候,可以提高速度.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-2800290286498858866?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/2800290286498858866/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=2800290286498858866' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2800290286498858866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2800290286498858866'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-42-list-comprehensions.html' title='Python Cookbook 4.2 用递推式构造列表(List Comprehensions)'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-7772053367152748489</id><published>2007-08-25T23:48:00.001+08:00</published><updated>2007-08-28T13:53:39.846+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>AsciiDoc中文标题-出现问题原因</title><content type='html'>昨天下载了AsciiDoc,想照着例子做个练习,没想到一开始就遇到了麻烦:&lt;br&gt;当把title项改成汉字的时候,总会报出类似:&lt;br&gt;ERROR: xxx.txt: line 7: closing [blockdef-listing] delimiter expected&lt;br&gt;的错误.&lt;br&gt;上网没有找到解决办法,只有自己分析了.给asciidoc.py下了断点:&lt;br&gt;写了下面这个测试文件:&lt;br&gt;&lt;br style="color: rgb(153, 51, 0);"&gt; &lt;span style="color: rgb(153, 51, 0);"&gt;这是一个标题&lt;/span&gt;&lt;br style="color: rgb(153, 51, 0);"&gt;&lt;span style="color: rgb(153, 51, 0);"&gt;========== &lt;/span&gt;&lt;br&gt;&lt;br&gt; 标题包含6个汉字,下面跟着12个=.&lt;br&gt;分别用UTF-8和UTF-8(No BOM)保存文件,对asciidoc.py进行跟踪:&lt;br&gt;&lt;br&gt;当跟到&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;title_len = char_len(title)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; ul_len = char_len(ul)&lt;br&gt;&lt;br&gt;&lt;/span&gt;时,发现title_len的返回值是6或7(带BOM),和我预想的12不同.&lt;br&gt;所以在底下执行&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if not (ul_len-3 &amp;lt; title_len &amp;lt; ul_len+3): return False&lt;/span&gt;&lt;br&gt;&lt;br&gt;就返回了,造成了不能正常执行完毕. &lt;br&gt;看来,原作者没有考虑到在中文环境下,一个汉字占2个ascii字符的位置的情况.&lt;br&gt;&lt;br&gt;所以我将那两行改成了&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;title_len = len(title)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;ul_len = len(ul) &lt;/span&gt;&lt;br&gt;&lt;br&gt;心想反正在UTF-8情况下,字符都是占用2个字节,只要直接比较len就可以了.&lt;br&gt;&lt;br&gt;结果完全出乎我的意料:&lt;br&gt;&lt;br&gt;title_len的值和ul_len的值变成了:18(21,带BOM的情况)和12!&lt;br&gt;看来UTF-8下,=还是一个字节,而汉字也不是2个字节!&lt;br&gt;&lt;br&gt;上网上找到下面一段话:&lt;br&gt;&lt;br&gt;UTF-8 使用一至四个字节为每个字符编码。128 个 ASCII 字符（Unicode 范围由 U+0000 至 U+007F）只需一个字节，带有变音符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及马尔代夫语（Unicode 范围由 U+0080 至 U+07FF）需要二个字节，其他基本多文种平面（BMP）中的字符（CJK属于此类-Qieqie注）使用&lt;b&gt;&lt;span style="color: red;"&gt;三个字节&lt;/span&gt;&lt;/b&gt;，其他 Unicode 辅助平面的字符使用四字节编码。&lt;br&gt;&lt;br&gt;看来,问题不是这么简单了.&lt;br&gt;&lt;br&gt;无奈,我注释掉&lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; if not (ul_len-3 &amp;lt; title_len &amp;lt; ul_len+3): return False&lt;/span&gt;&lt;br&gt;&lt;br&gt;这样就可以编译带中文标题的文件了,但不知道对别的什么情况有影响了.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-7772053367152748489?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/7772053367152748489/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=7772053367152748489' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7772053367152748489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7772053367152748489'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/asciidoc.html' title='AsciiDoc中文标题-出现问题原因'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-2376671221268916891</id><published>2007-08-24T09:58:00.001+08:00</published><updated>2007-08-28T13:53:39.846+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 4.1 复制(拷贝)对象</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你想复制一个对象.因为在Python中,无论你把对象做为参数传递,做为函数返回值,都是引用传递的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;标准库中的copy模块提供了两个方法来实现拷贝.一个方法是copy,它返回和参数包含内容一样的对象.&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import copy&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;new_list = copy.copy(existing_list)&lt;/span&gt;&lt;br&gt;&lt;br&gt;有些时候,你希望对象中的属性也被复制,可以使用deepcopy方法:&lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import copy&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;new_list_of_dicts = copy.deepcopy(existing_list_of_dicts)&lt;/span&gt;&lt;br&gt;&lt;br&gt;当你对一个对象赋值的时候(做为参数传递,或者做为返回值),Python和Java一样,总是传递原始对象的引用,而不是一个副本.其它一些语言当赋值的时候总是传递副本.Python从不猜测用户的需求 ,如果你想要一个副本,你必须显式的要求.&lt;br&gt;Python的行为很简单,迅速,而且一致.然而,如果你需要一个对象拷贝而并没有显式的写出来,会出现问题的,比如:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; a = [1, 2, 3]&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; b = a&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; b.append(5)&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; print a, b &lt;br&gt;&lt;b&gt;[1, 2, 3, 5] [1, 2, 3, 5]&lt;/b&gt;&lt;/pre&gt;在这里,变量a和b都指向同一个对象(一个列表),所以,一旦你修改了二者之一,另外一个也会受到影响.无论怎样,都会修改原来的对象.&lt;br&gt;注意:&lt;br&gt;要想成为一个Python高手,首先要注意的问题就是对象的变更操作和赋值,它们都是针对对象的引用操作的.一个语句比如a = []将a重新绑定给一个新对象,但不会影响以前的对象.然而,对象复制却不同,当对象复制后,对象变更操作就有了区别. &lt;br&gt;如果你想修改一个对象,而且想让原始的对象不受影响,那你就需要对象复制.正如本节说的一样,你可以使用copy模块中的两个方法来实现需求.一般的,可以使用copy.copy,它可以进行对象的浅复制(shallow copy),它复制了对象,但对于对象中的元素,依然使用引用.&lt;br&gt;浅复制,有时无法获得一个和原来对象完全一致的副本,如果你想修改对象中的元素,不仅仅是对象本身的话:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;gt;&amp;gt;&amp;gt; list_of_lists = [ [&amp;#39;a&amp;#39;], [1, 2], [&amp;#39;z&amp;#39;, 23] ]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; copy_lol = copy.copy(lists_of_lists) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; copy_lol[1].append(&amp;#39;boo&amp;#39;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; print list_of_lists, copy_lol &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;b style="color: rgb(204, 0, 0);"&gt;[[&amp;#39;a&amp;#39;], [1, 2, &amp;#39;boo&amp;#39;], [&amp;#39;z&amp;#39;, 23]] [[&amp;#39;a&amp;#39;], [1, 2, &amp;#39;boo&amp;#39;], [&amp;#39;z&amp;#39;, 23]]&lt;/b&gt;&lt;br&gt;&lt;br&gt;在这里,变量list_of_lists,copy_lol指向了两个不同的对象,所以我们可以修改它们任何一个, 而不影响另外一个.然而,如果我们修改了一个对象中的元素,那么另一个也会受影响,因为它们中的元素还是共享引用.&lt;br&gt;如果你希望复制一个容器对象,以及它里面的所有元素(包含元素的子元素),使用copy.deepcopy,这个方法会消耗一些时间和空间,不过,如果你需要完全复制,这是唯一的方法.&lt;br&gt;对于一般的浅拷贝,使用copy.copy就可以了,当然,你需要了解你要拷贝的对象.要复制列表L,使用list(L),要复制一个字典d,使用dict(d),要复制一个集合s,使用set(s),这样,我们总结出一个规律,如果你要复制一个对象o,它属于内建的类型t,那么你可以使用t(o)来 获得一个拷贝.dict也提供了一个复制版本,dict.copy,这个和dict(d)是一样,我推荐你使用后者,这个使得代码更一致,而且还少几个字符.&lt;br&gt;要复制一个别的类型,无论是你自己写的还是使用库中的,使用copy.copy,如果你自己写一个类,没有必要费神去写clone和copy函数,如果你想定义自己的类复制的方式,实现一个__copy__,或者__getstate__和__setstate__.如果你想定义自己类型的deepcopy,实现方法__deepcopy__. &lt;br&gt;注意你不用复制不可修改对象(string,数字,元组),因为你不用担心修改它们.如果你想尝试一下复制,依然会得到原来的.虽然无伤大雅,不过真的浪费尽力:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; s = &amp;#39;cat&amp;#39; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; t = copy.copy(s) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; s is t &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;b&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;True&lt;/span&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/b&gt;is操作符用于不仅判断两个对象是否完全一致,而且是同一个对象(is判断标识符,要比较内容,使用==),判断标识符是否相等对于不可修改对象没有什么意义.然而 ,判断标识符对于可修改对象有时候是很重要的,比如,你不确定a和b是否指向同一个对象,使用a is b会立刻得到结果.这样你可以自己判断是否需要使用对象拷贝.&lt;br&gt;注意:&lt;br&gt;你可以使用另一种拷贝方式,给定一个列表L,无论是完整切片L[:]或者列表解析[x for x in L],都会获得L的浅拷贝,试试L+[],L*1...但是上面两种方法都会使人迷惑,使用list(L)最清晰和快速,当然,由于历史原因,你可能会经常看到L[:]的写法. &lt;br&gt;对于dict,你可能见过下面的复制方法:&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; for somekey in d: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;... &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;    d1[somekey] = d[somekey]&lt;/span&gt;&lt;br&gt;&lt;br&gt;或者更简单一些的方法,d1={},d1.update(d),无论怎样,这些代码都是缺乏效率的,使用d1=dict(d)吧.&lt;br&gt;&lt;br style="font-weight: bold;"&gt; &lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;copy(x)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Shallow copy operation on arbitrary Python objects.&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; See the module&amp;#39;s __doc__ string for more info. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;deepcopy&lt;/span&gt;(x, memo=None, _nil=[])&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Deep copy operation on arbitrary Python objects.&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; See the module&amp;#39;s __doc__ string for more info.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-2376671221268916891?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/2376671221268916891/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=2376671221268916891' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2376671221268916891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2376671221268916891'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-41.html' title='Python Cookbook 4.1 复制(拷贝)对象'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-6214591264816418069</id><published>2007-08-23T14:45:00.001+08:00</published><updated>2007-08-28T13:53:39.846+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.16 查看外汇兑换汇率</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你想定期的查看两种货币间的兑换汇率(用linux的crontab或window的计划任务),从网上获得,并获得邮件通知.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;本节的代码和其它类似需求很相似,都是从网上获得数据,比如汇率,股票价格,甚至天气情况.让我们在这里看看如果获得美元和加元的汇率 ,从加拿大银行的网页获得.&lt;br&gt;&lt;pre&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import httplib&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import smtplib&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; # configure script&amp;#39;s parameters here&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thresholdRate = 1.30&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;smtpServer = &amp;#39; &lt;a href="http://smtp.freebie.com"&gt;smtp.freebie.com&lt;/a&gt;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;fromaddr = &amp;#39;&lt;a href="mailto:foo@bar.com"&gt;foo@bar.com&lt;/a&gt;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;toaddrs = &amp;#39;&lt;a href="mailto:your@corp.com"&gt;your@corp.com&lt;/a&gt;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# end of configuration&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;url = &amp;#39;/en/financial_markets/csv/exchange_eng.csv&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;conn = httplib.HTTPConnection(&amp;#39;&lt;a href="http://www.bankofcanada.ca"&gt; www.bankofcanada.ca&lt;/a&gt;&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;conn.request(&amp;#39;GET&amp;#39;, url)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;response =  conn.getresponse( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;data = response.read( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;start = data.index(&amp;#39;United States Dollar&amp;#39;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;line = data[start:data.index(&amp;#39;\n&amp;#39;, start)]    # get the relevant line&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; rate = line.split(&amp;#39;,&amp;#39;)[-1]                   # last field on the line&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if float(rate) &amp;lt; thresholdRate:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;   # send email&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;   msg = &amp;#39;Subject: Bank of Canada exchange rate alert %s&amp;#39; % rate&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;   server = smtplib.SMTP(smtpServer)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;   server.sendmail(fromaddr, toaddrs, msg)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;   server.quit( )&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;conn.close( )&lt;/span&gt;&lt;/pre&gt;当需要知道外汇汇率时,最好能自动进行货币转换.本节的代码很直白,访问网页,获得CSV,它里面描述了汇率信息:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; Date (m/d/year),11/12/2004,11/15/2004, ... ,11/19/2004,11/22/2004&lt;br&gt;$Can/US closing rate,1.1927,1.2005,1.1956,1.1934,1.2058,1.1930, &lt;br&gt;United States Dollar,1.1925,1.2031,1.1934,1.1924,1.2074,1.1916,1.1844&lt;br&gt;...&lt;/pre&gt;这个脚本首先查找需要的币种(United States Dollar),然后找到最后, 获得今天的数据.如果你不太明天它是如何工作的,可以分开来看:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;US = data.find(&amp;#39;United States Dollar&amp;#39;)  # find the index of the currency&lt;br&gt;endofUSline = data.index(&amp;#39;\n&amp;#39;, US)      # find index for that line end &lt;br&gt;USline = data[US:endofUSline]           # slice to make one string &lt;br&gt;rate = USline.split(&amp;#39;,&amp;#39;)[-1]            # split on &amp;#39;,&amp;#39; and return last field&lt;/pre&gt;最后用email发送感兴趣的信息,你自己可以配置自己喜欢的信息.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-6214591264816418069?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/6214591264816418069/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=6214591264816418069' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6214591264816418069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6214591264816418069'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-316.html' title='Python Cookbook 3.16 查看外汇兑换汇率'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-2792526187158619832</id><published>2007-08-23T14:32:00.001+08:00</published><updated>2007-08-28T13:53:39.847+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.15 计算信用卡的校验和</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你想计算一下自己信用卡的校验和,并判读它是否满足Luhn标准.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;Luhn模10是信用卡号的标准,在Python中并没有对应的内建函数,不过我们可以自己实现:&lt;br&gt;&lt;pre&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; def cardLuhnChecksumIsValid(card_number):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;    &amp;quot;&amp;quot;&amp;quot; checks to make sure that the card passes a luhn mod-10 checksum &amp;quot;&amp;quot;&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;    sum = 0&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;    num_digits = len(card_number)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;    oddeven = num_digits &amp;amp; 1&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;    for count in range(num_digits):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;        digit = int(card_number[count])&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;        if not (( count &amp;amp; 1 ) ^ oddeven):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;            digit = digit * 2&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;        if digit &amp;gt; 9:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;             digit = digit - 9&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;        sum = sum + digit&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;    return (sum % 10) == 0 &lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;/pre&gt;本节的代码最初用于 一个电子商务系统.&lt;br&gt;它可以节省你的时间,用于判断用户提供的信用卡号是否是有效的,因为你不用花钱去验证卡号是否有效.这个代码也可以广泛使用因为许多政府都使用Luhn校验算法.&lt;br&gt;如果你想用一行代码实现上面的功能,你真的找错书了(也许你应该去读Perl Cookbook),当然,我也提供一个版本,试试:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; checksum = lambda a: (&lt;br&gt;  10 - sum([int(y)*[7,3,1][x%3] for x, y in enumerate(str(a)[::-1])])%10)%10&lt;/pre&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-2792526187158619832?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/2792526187158619832/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=2792526187158619832' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2792526187158619832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2792526187158619832'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-315.html' title='Python Cookbook 3.15 计算信用卡的校验和'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-1360559555966700667</id><published>2007-08-23T14:23:00.001+08:00</published><updated>2007-08-28T13:53:39.847+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.14 将Python做为简易计算器</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你想将Python做为一个简易的计算器,计算十进制小数(非float),并能整齐的将结果显示出来.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;为了实现计算,我们可以使用decimal模块,我们接收输入行,用计算符号将它们连接起来,接收空行来显示当前结果,q来结束程序. &lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;import decimal, re, operator&lt;br&gt;parse_input = re.compile(r&amp;#39;&amp;#39;&amp;#39;(?x)  # allow comments and whitespace in the RE&lt;br&gt;              (\d+\.?\d*)          # number with optional decimal part &lt;br&gt;              \s*                  # optional whitespace&lt;br&gt;              ([-+/*])             # operator&lt;br&gt;              $&amp;#39;&amp;#39;&amp;#39;)                # end-of-string&lt;br&gt;oper = { &amp;#39;+&amp;#39;: operator.add, &amp;#39;-&amp;#39;:  operator.sub,&lt;br&gt;         &amp;#39;*&amp;#39;: operator.mul, &amp;#39;/&amp;#39;: operator.truediv,&lt;br&gt;       }&lt;br&gt;total = decimal.Decimal(&amp;#39;0&amp;#39;)&lt;br&gt;def print_total( ):&lt;br&gt;    print &amp;#39;==  ==  =\n&amp;#39;, total&lt;br&gt;print &amp;quot;&amp;quot;&amp;quot;Welcome to Adding Machine:  &lt;br&gt;Enter a number and operator, &lt;br&gt;an empty line to see the current subtotal,&lt;br&gt;or q to quit: &amp;quot;&amp;quot;&amp;quot;&lt;br&gt;while True:&lt;br&gt;    try:&lt;br&gt;        tape_line = raw_input( ).strip( )&lt;br&gt;    except EOFError:&lt;br&gt;        tape_line = &amp;#39;q&amp;#39; &lt;br&gt;    if not tape_line:&lt;br&gt;        print_total( )&lt;br&gt;        continue&lt;br&gt;    elif tape_line == &amp;#39;q&amp;#39;:&lt;br&gt;        print_total( )&lt;br&gt;        break&lt;br&gt;    try:&lt;br&gt;        num_text, op = parse_input.match(tape_line).groups( ) &lt;br&gt;    except AttributeError:&lt;br&gt;        print &amp;#39;Invalid entry: %r&amp;#39; % tape_line&lt;br&gt;        print &amp;#39;Enter number and operator, empty line for total, q to quit&amp;#39;&lt;br&gt;        continue&lt;br&gt;    total = oper[op](total,  decimal.Decimal(num_text))&lt;/pre&gt;Python的交互式解析器经常可以用于计算器,不过我们写的计算器也能达到相同的目的.比如,对于一个类似表达式2345634+2894756-2345823 来说,要保证你输入的数字都是正确的也很不容易.我们的计算器用简单的,整齐的方式显示数字,让你更清楚自己都输入了什么数字.另外,decimal模块计算数字的方式和我们真实生活中是一样的,而不是使用float计算.&lt;br&gt;当你在一个shell中运行这个脚本的时候(这个脚本不能在交互式解析器中使用),脚本提示你输入, 然后就等待.输入一个数字(可以是小数),一个运算符(+,-,*,/),然后回车.这个脚本开始累加数字.要看当前的计算结果,输入回车就可以了.要退出程序,输入q就可以了.这个脚本实现了最简单的计算器,并提供了简易的界面.&lt;br&gt;本节的代码相当简单,所以可以有很多加强的地方.一个比较有用的就是记录下输入.实现起来很简单,在循环前处理就好了:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;tapefile = open(&amp;#39; tapefile.txt&amp;#39;, &amp;#39;a&amp;#39;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;然后输入用户输入就可以了,注意使用try/except:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;tapefile.write(tape_line+&amp;#39;\n&amp;#39;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;你也可以在输出结果的时候,同时将结果写入文件中去:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; def print_total( ):&lt;br&gt;    print &amp;#39;==  ==  =\n&amp;#39;, total&lt;br&gt;    tapefile.write(&amp;#39;==  ==  =\n&amp;#39; + str(total) + &amp;#39;\n&amp;#39;)&lt;/pre&gt;file对象的write方法并不自己添加回车,所以我们需要自己写入回车符.另外我们也可以使用别的方式来实现这个功能:&lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;print &amp;gt;&amp;gt;tapefile, &amp;#39;==  ==  =\n&amp;#39;, total&lt;/span&gt;&lt;br&gt;&lt;br&gt;有些人不喜欢print &amp;gt;&amp;gt; somefile的写法,不过在这里真的很方便.&lt;br&gt;另外的优化比如缓冲输入,或者添加clear方法,甚至添加一个GUI界面,当然,有兴趣的读者可以自己实现.&lt;br&gt;本节中使用的一个要点就是oper字典,它将字符(+,-,*,/)和内建的operator方法关联起来,如果没有使用这个,就要使用一堆if/elif语句了,比如: &lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;if op == &amp;#39;+&amp;#39;:&lt;br&gt;    total = total + decimal.Decimal(num_text)&lt;br&gt;elif op == &amp;#39;-&amp;#39;:&lt;br&gt;    total = total - decimal.Decimal(num_text)&lt;br&gt;elif op == &amp;#39;*&amp;#39;:&lt;br&gt;    &amp;lt;line_annotation&amp;gt;... and so on ...&amp;lt;/line_annotation&amp;gt; &lt;/pre&gt;Python的字典是很灵活和强大的,可以让代码更简洁,可维护,并去掉重复代码.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-1360559555966700667?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/1360559555966700667/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=1360559555966700667' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1360559555966700667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1360559555966700667'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-314-python.html' title='Python Cookbook 3.14 将Python做为简易计算器'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-8824733546296673572</id><published>2007-08-22T14:12:00.001+08:00</published><updated>2007-08-28T13:53:39.847+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.13 格式化十进制小数转换为货币形式</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要做一些简单的金融计算,并希望将结果表示为欧洲货币形式.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;在新的decimal模块中,有一个修改过的moneyfmt函数,我们可以使用它来实现功能.&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; import decimal&lt;br&gt;&amp;quot;&amp;quot;&amp;quot; calculate Italian invoice taxes given a subtotal. &amp;quot;&amp;quot;&amp;quot;&lt;br&gt;def italformat(value, places=2, curr=&amp;#39;EUR&amp;#39;, sep=&amp;#39;.&amp;#39;, dp=&amp;#39;,&amp;#39;, pos=&amp;#39;&amp;#39;, neg=&amp;#39;-&amp;#39;, &lt;br&gt;               overall=10):&lt;br&gt;    &amp;quot;&amp;quot;&amp;quot; Convert Decimal ``value&amp;#39;&amp;#39; to a money-formatted string.&lt;br&gt;    places:  required number of places after the decimal point&lt;br&gt;    curr:    optional currency symbol before the sign (may be blank) &lt;br&gt;    sep:     optional grouping separator (comma, period, or blank) every 3&lt;br&gt;    dp:      decimal point indicator (comma or period); only specify as&lt;br&gt;                 blank when places is zero&lt;br&gt;    pos:     optional sign for positive numbers: &amp;quot;+&amp;quot;, space or blank &lt;br&gt;    neg:     optional sign for negative numbers: &amp;quot;-&amp;quot;, &amp;quot;(&amp;quot;, space or blank&lt;br&gt;    overall: optional overall length of result, adds padding on the&lt;br&gt;                 left, between the currency symbol and digits &lt;br&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;br&gt;    q = decimal.Decimal((0, (1,), -places))             # 2 places --&amp;gt; &amp;#39;0.01&amp;#39;&lt;br&gt;    sign, digits, exp = value.quantize(q).as_tuple( )&lt;br&gt;    result = [  ]&lt;br&gt;    digits = map(str, digits) &lt;br&gt;    append, next = result.append, digits.pop&lt;br&gt;    for i in range(places):&lt;br&gt;        if digits:&lt;br&gt;            append(next( ))&lt;br&gt;        else:&lt;br&gt;            append(&amp;#39;0&amp;#39;)&lt;br&gt;    append(dp)&lt;br&gt;    i = 0&lt;br&gt;    while digits: &lt;br&gt;        append(next( ))&lt;br&gt;        i += 1&lt;br&gt;        if i == 3 and digits:&lt;br&gt;            i = 0&lt;br&gt;            append(sep)&lt;br&gt;    while len(result) &amp;lt; overall:&lt;br&gt;        append(&amp;#39; &amp;#39;)&lt;br&gt;    append(curr)&lt;br&gt;    if sign: append(neg) &lt;br&gt;    else: append(pos)&lt;br&gt;    result.reverse( )&lt;br&gt;    return &amp;#39;&amp;#39;.join(result)&lt;br&gt;# get the subtotal for use in calculations&lt;br&gt;def getsubtotal(subtin=None):&lt;br&gt;    if subtin == None:&lt;br&gt;        subtin = input(&amp;quot;Enter the subtotal: &amp;quot;) &lt;br&gt;    subtotal = decimal.Decimal(str(subtin))&lt;br&gt;    print &amp;quot;\n subtotal:                   &amp;quot;, italformat(subtotal)&lt;br&gt;    return subtotal&lt;br&gt;# specific Italian tax law functions&lt;br&gt;def cnpcalc(subtotal):&lt;br&gt;    contrib = subtotal *  decimal.Decimal(&amp;#39;.02&amp;#39;)&lt;br&gt;    print &amp;quot;+ contributo integrativo 2%:    &amp;quot;, italformat(contrib, curr=&amp;#39;&amp;#39;)&lt;br&gt;    return contrib&lt;br&gt;def vatcalc(subtotal, cnp):&lt;br&gt;    vat = (subtotal+cnp) * decimal.Decimal (&amp;#39;.20&amp;#39;)&lt;br&gt;    print &amp;quot;+ IVA 20%:                      &amp;quot;, italformat(vat, curr=&amp;#39;&amp;#39;)&lt;br&gt;    return vat&lt;br&gt;def ritacalc(subtotal):&lt;br&gt;    rit = subtotal * decimal.Decimal(&amp;#39;.20&amp;#39;)&lt;br&gt;    print &amp;quot;-Ritenuta d&amp;#39;acconto 20%:        &amp;quot;, italformat(rit, curr=&amp;#39;&amp;#39;) &lt;br&gt;    return rit&lt;br&gt;def dototal(subtotal, cnp, iva=0, rit=0):&lt;br&gt;    totl = (subtotal+cnp+iva)-rit&lt;br&gt;    print &amp;quot;                     TOTALE: &amp;quot;, italformat(totl)&lt;br&gt;    return totl&lt;br&gt;# overall calculations report &lt;br&gt;def invoicer(subtotal=None, context=None):&lt;br&gt;    if context is None:&lt;br&gt;        decimal.getcontext( ).rounding=&amp;quot;ROUND_HALF_UP&amp;quot;     # Euro rounding rules&lt;br&gt;    else:&lt;br&gt;        decimal.setcontext(context)                       # set to context arg &lt;br&gt;    subtot = getsubtotal(subtotal)      &lt;br&gt;    contrib = cnpcalc(subtot)&lt;br&gt;    dototal(subtot, contrib, vatcalc(subtot, contrib), ritacalc(subtot))&lt;br&gt;if _ _name_ _==&amp;#39;_ _main_ _&amp;#39;:&lt;br&gt;    print &amp;quot;Welcome to the invoice calculator&amp;quot; &lt;br&gt;    tests = [100, 1000.00, &amp;quot;10000&amp;quot;, 555.55]&lt;br&gt;    print &amp;quot;Euro context&amp;quot;&lt;br&gt;    for test in tests:&lt;br&gt;        invoicer(test)&lt;br&gt;    print &amp;quot;default context&amp;quot;&lt;br&gt;    for test in tests:&lt;br&gt;        invoicer(test, context= decimal.DefaultContext)&lt;/pre&gt;意大利的税务计算是非常复杂的,所以本节的例子也就比较长.本节的代码只适用于意大利的货品计价用户.我自己用手计算发现太累了,所以写了一个小的Python脚本来计算它.我使用decimal模块来实现这个例子,也是要说明当涉及金钱的计算的时候,千万不要使用float.&lt;br&gt;为什么说decimal最适合货币计算并不是立刻就能明白的.因为虽然计算很简单,可是对于结果的显示就不那么简单了.本节的italformat函数基于Hettinger &amp;#39;s &lt;i&gt;moneyfmt&lt;/i&gt; ,那个在Python标准库中的decimal中有介绍.我进行了一些修改,为了获得自己希望的结果.一个明显的修改就是添加了overall参数,这个参数使用overall来构造一个数字,并在数字和货币符号间添加了空格.这样对输出能控制好格式.&lt;br&gt;注意我在计算小节的部分,使用了&lt;tt&gt;subtotal =&lt;/tt&gt; &lt;tt&gt;decimal.Decimal(str(subtin))&lt;/tt&gt;. 这样就能使用float计算我们需要的结果. &lt;br&gt;当然,如果你需要使用US $来做为货币符号,或者别的东西,改起来也是很简单的.比如,你要输出$,可以这样设置参数:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;def USformat(value, places=2, curr=&amp;#39;$&amp;#39;, sep=&amp;#39;,&amp;#39;, dp=&amp;#39;.&amp;#39;, pos=&amp;#39;&amp;#39;, neg=&amp;#39;-&amp;#39;,&lt;br&gt;             overall=10): &lt;br&gt;...&lt;/pre&gt;如果你可能要同时处理多种货币格式,你可以修改这个函数,让它接收一个字典为参数,或者使用别的方式来传递参数.理论上,你可以使用locale模块来处理和地区相关的问题,比如货币格式,但在实际中我很少使用locale,所以功能的具体实现就交给读者吧.&lt;br&gt;不同的国家有不同的保留小数的方式,decimal使用&lt;tt&gt;ROUND_HALF_EVEN&lt;/tt&gt; 做为默认方式,然而,欧洲货币使用&lt;tt&gt;ROUND_HALF_UP,为了使用不同的规则,修改decimal的context,也许修改后的结果不会有什么变化,但是还是要小心这些细微的差别. &lt;br&gt;你也可以更彻底的修改context,比如自己写context,对于修改context,无论是使用getcontext来获得,还是使用setcontext(mycontexts),都会保存它的值,一直到线程中止.在产品中,一定要注意使用合适的context,尤其是保留小数的方法.因为不同的国家可能是不同的.&lt;br&gt;&lt;br&gt;&lt;/tt&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt; &lt;span style="font-weight: bold;"&gt;decimal.getcontext()&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Returns this thread&amp;#39;s context.&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If this thread does not yet have a context, returns&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a new context and sets this thread&amp;#39;s context. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; New contexts are copies of DefaultContext.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;decimal.setcontext(context)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Set this thread&amp;#39;s context to context.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-8824733546296673572?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/8824733546296673572/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=8824733546296673572' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8824733546296673572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8824733546296673572'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-313.html' title='Python Cookbook 3.13 格式化十进制小数转换为货币形式'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-8323860763939466448</id><published>2007-08-22T12:17:00.001+08:00</published><updated>2007-08-28T13:53:39.847+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.12 十进制小数计算</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要进行一些简单的小数计算,但是需要得到定点小数的结果,而不是Python默认的float类型.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;为了获得最通用,最准确的结果,可以使用decimal模块.&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; &amp;gt;&amp;gt;&amp;gt; import decimal&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; d1 = decimal.Decimal(&amp;#39;0.3&amp;#39;)   # assign a decimal-number object&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; d1/3                          # try some division&lt;br&gt;&lt;b&gt;Decimal(&amp;quot;0.1&amp;quot;)&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; (d1/3)*3                      # can we get back where we started? &lt;br&gt;&lt;b&gt;Decimal(&amp;quot;0.3&amp;quot;)&lt;/b&gt;&lt;/pre&gt;对于新使用Python的用户来说(尤其是没有使用别的语言的float类型的用户),经常会对简单的计算结果表示惊奇,比如:&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; f1 = .3                     # assign a float&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; f1/3                        # try some division &lt;br&gt;&lt;b&gt;0.099999999999999992&lt;/b&gt;&lt;br&gt;&amp;gt;&amp;gt;&amp;gt; (f1/3)*3                    # can we get back where we started?&lt;br&gt;&lt;b&gt;0.29999999999999999&lt;/b&gt;&lt;/pre&gt;二进制浮点运算是Python中默认的运算方式.在Python的FAQ中有详细的说明.&lt;br&gt;很多用户,当然,不喜欢只能使用浮点数,他们需要自定义精度, 或者进行金融计算.而且想获得可预知的结果.&lt;br&gt;新的decimal模块对你计算过程的上下文进行了很好的控制,它允许你自定义精度,或者保留定义保留小数的方法.当然,如果你只是想进行简单的计算,并获得可以预知的结果,decimal默认的设置就能很好的工作了.&lt;br&gt;只需要注意几点:你可以传递整数,字符串,元组或者一个decimal对象来创建新的decimal对象,但是如果你想从一个float创建decimal,使用str(n),而不是简单的n.另外 ,decimal对象也可以和别的对象交互(简单的四则运算),如整数,长整数,别的decimal对象,但是不能和float交互.这个限制的强制的.decimal被引入Python,提供了精度控制和结果的可预知性,这都是float所不具有的.如果把一个decimal和一个float共同计算,那么就不能达到目的.decimal对象,可以被转换为别的对象,比如int,long,float等,正如我们期望的那样.&lt;br&gt;还要注意的是,decimal依然是浮点小数,而不是定点小数,如果你需要使用定点小数,可以参考Tim  Peter的FixPoint.同样,Python现在也没有money类型,你可以参考下一节来自己实现一个money类型.最后将一点,不是很明确的,当计算的中间结果产生的小数位多于输入的数字时,你可以保留它的小数一用于后续的计算,当算到最后时在进行小数保留,或者你可以在每一步都保留小数,不同的书中推荐不同的做法,我个人倾向于前者,因为它更简单和方便.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-8323860763939466448?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/8323860763939466448/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=8323860763939466448' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8323860763939466448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8323860763939466448'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-312.html' title='Python Cookbook 3.12 十进制小数计算'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4169381974128669628</id><published>2007-08-21T10:26:00.001+08:00</published><updated>2007-08-28T13:53:39.848+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.11 调度命令</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要在特定的时间调度命令的执行.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;标准库中的sched库可以完成这个功能:&lt;br&gt;&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt;import time, os, sys, sched&lt;br&gt; schedule = sched.scheduler(time.time, time.sleep)&lt;br&gt;def perform_command(cmd, inc):&lt;br&gt;    schedule.enter(inc, 0, perform_command, (cmd, inc)) # re-scheduler&lt;br&gt;    os.system(cmd)&lt;br&gt;def main(cmd, inc=60):&lt;br&gt;    schedule.enter (0, 0, perform_command, (cmd, inc))   # 0==right now&lt;br&gt;    schedule.run( )&lt;br&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39; :&lt;br&gt;    numargs = len(sys.argv) - 1&lt;br&gt;    if numargs &amp;lt; 1 or numargs &amp;gt; 2:&lt;br&gt;        print &amp;quot;usage: &amp;quot; +  sys.argv[0] + &amp;quot; command [seconds_delay]&amp;quot;&lt;br&gt;        sys.exit(1)&lt;br&gt;    cmd = sys.argv[1]&lt;br&gt;    if numargs &amp;lt; 3:&lt;br&gt;        main(cmd)&lt;br&gt;    else:&lt;br&gt;        inc = int(sys.argv[2])&lt;br&gt;        main(cmd, inc)&lt;/pre&gt; 本节和上节完成了类似的功能,不同的是,上节用自己实现代码的方式,而本节使用sched库来完成.&lt;br&gt;sched很简单,强大和灵活.使用sched调度的任务在给定时间一定会执行.要使用sched,你首先创建scheduler对象,比如schedule,并包含两个参数.第一个参数用于查找当前时间,它返回一个从标准时间到现在的整数,我们通常称为epoch.第二个参数用于表示延迟多少时间.你可以使用人工的方法来判断时间,比如,使用sched做为模拟程序,当然,手动使用sched衡量时间是高阶应用,在这里不做讨论. &lt;br&gt;一点你拥有了scheduler对象s,你可以通过s.enter来调度任务,让该任务在N秒后执行(可以传递0,表示立刻执行),也可以是使用s.enterabs,用于设定一个绝对时间.无论那种情况,你传递一个时间(绝对或相对),一个优先级(如果同时有多个任务执行,低优先级的先执行),要执行的函数,还有一个元组表示调用函数的参数.上面两个方法都返回一个事件标识符,一个随机的标识符,用于后来使用s.cancel来取消它.&lt;br&gt;当完成调度后, 你可以使用s.run来执行,它一直会执行到调度队列为空.在本节中,我们演示了如何调度一个周期执行的事件,函数perform_command做的第一件事情就是重新调度事件,然后再执行.这样做,调度队列永不会为空,而且perform_command函数会被定期执行,在这个函数中,自调度是一个非常重要的写法,不但在sched中,在其它的地方,如果你希望一个事件一旦触发,就会周期的进行,可以使用这个方法.&lt;br&gt;尽管本节只描述了一个简单的例子,sched依然具有一些有点, 相对于自己写代码来说.在上一节,在cmd执行的期间,需要delay一段时间,假如cmd需要等待的时间是个变量(这也是最常见的情况,比如等待网络,或者比较繁忙的服务等),那么这个任务就不是绝对的周期执行.在本节中,延迟是在cmd执行之前来决定的,所以周期能够保证.如果运行cmd的时间偶尔超过了inc的值,调度会暂时的落后,但很快会在后面赶上,只要cmd的平均运行时间小于inc:sched不会漏掉事件(如果你需要放弃一些事件,使用sched.cancel ).&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;sched.scheduler.enter(self, delay, priority, action, argument)&lt;/span&gt; unbound sched.scheduler method&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A variant that specifies the time as a relative time. &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This is actually the more commonly used interface.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;sched.scheduler.enterabs(self, time, priority, action, argument) &lt;/span&gt;unbound sched.scheduler method&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Enter a new event in the queue at an absolute time. &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Returns an ID for the event which can be used to remove it,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if necessary.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;sched.scheduler.run(self)&lt;/span&gt; unbound sched.scheduler method&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Execute events until the queue is empty. &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; When there is a positive delay until the first event, the delay function is called and the event is left in the queue; otherwise, the event is removed from the queue and executed (its action function is called, passing it the argument).&amp;nbsp; If&amp;nbsp; the delay function returns prematurely, it is simply restarted. &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; It is legal for both the delay function and the action function to to modify the queue or to raise an exception; exceptions are not caught but the scheduler&amp;#39;s state remains well-defined so run() may be called again. &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A questionably hack is added to allow other threads to run: just after an event is executed, a delay of 0 is executed, to avoid monopolizing the CPU when other threads are also&amp;nbsp;&amp;nbsp; runnable.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; sched.scheduler.cancel(self, event)&lt;/span&gt; unbound sched.scheduler method&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Remove an event from the queue.&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This must be presented the ID as returned by enter(). If the event is not in the queue, this raises RuntimeError. &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4169381974128669628?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4169381974128669628/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4169381974128669628' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4169381974128669628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4169381974128669628'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-311.html' title='Python Cookbook 3.11 调度命令'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4239291974462622357</id><published>2007-08-20T17:42:00.001+08:00</published><updated>2007-08-28T13:53:39.848+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.10 重复执行命令</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要重复的执行一个命令,并且可以指定优先级.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;time.sleep函数提供了简单的解决方案.&lt;br&gt;&lt;br&gt;&lt;pre style="color: rgb(204, 0, 0);"&gt; import time, os, sys&lt;br&gt;def main(cmd, inc=60):&lt;br&gt;    while True:&lt;br&gt;        os.system(cmd)&lt;br&gt;        time.sleep(inc)&lt;br&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39; :&lt;br&gt;    numargs = len(sys.argv) - 1&lt;br&gt;    if numargs &amp;lt; 1 or numargs &amp;gt; 2: &lt;br&gt;        print &amp;quot;usage: &amp;quot; + sys.argv[0] + &amp;quot; command [seconds_delay]&amp;quot;&lt;br&gt;        sys.exit(1)&lt;br&gt;    cmd = sys.argv[1]&lt;br&gt;    if numargs &amp;lt; 3:&lt;br&gt;        main(cmd)&lt;br&gt;    else:&lt;br&gt;        inc = int(sys.argv [2])&lt;br&gt;        main(cmd, inc)&lt;/pre&gt;你可以使用本节的代码来偶然的执行某些命令(如传送),或者重复执行某些指令,如通知浏览器重复加载一个URL,使得总是能获得最新的网页内容.本节代码的结构是使用一个main函数体和使用&lt;tt&gt;if _ _name_ _==&amp;#39;_ _main_ _&amp;#39;语句来组织的.这是当脚本用于单独执行时的习惯性编写方式.代码体检查输入参数,然后调用main方法,这是组织代码的最好办法,这样也方便别的模块使用该模块的代码. &lt;br&gt;main函数接收一个cmd参数,它表示你要执行的系统命令的字符串,还有一个可选参数,及执行间隔时间,默认是60秒.main方法是一个循环过程,使用os.system来执行命令,并使用time.sleep来等待.&lt;br&gt;脚本的主体用于判断参数,参数都包含在sys.argv里面,第一个参数,sys.argv[0],是脚本的名称,一般可以用于标识自己.接下来,脚本判断了其余的一个或两个参数,第一个(必须)是要执行的命令,另一个(可选)是重复执行的时间间隔.(在传递命令的时候,最好使用引号将字符串包含起来,以免shell出现解析错误),如果没有第二个参数,main函数将使用默认的值,60秒. &lt;br&gt;需要注意的时候,如果有第二个参数,需要将它从string转换为int(sys.argv里面总是string),只要使用内建的int方法就可以了.&lt;br&gt;如果第二个参数不是合法的字符(包含非数字序列),调用int方法会抛出异常,程序中止.因为Python的一个设计原则就是:&amp;quot;错误不能隐藏,除非声明需要隐藏&amp;quot;.&lt;br&gt;&lt;/tt&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt; &lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;time.sleep(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sleep(seconds)&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Delay execution for a given number of seconds.&amp;nbsp; The argument may be&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a floating point number for subsecond precision. &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4239291974462622357?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4239291974462622357/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4239291974462622357' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4239291974462622357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4239291974462622357'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-310.html' title='Python Cookbook 3.10 重复执行命令'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-6808500405827851060</id><published>2007-08-15T09:54:00.001+08:00</published><updated>2007-08-28T13:53:39.848+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.9 转换时区</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;假如你现在在西班牙,你需要知道中国发生的事件的西班牙时间.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;对于datetime对时区的支持,可以从第三方包dateutil获得,这里有一个方法来设置本地时区,并打印出时间来看它是否有效:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; from dateutil import tz&amp;nbsp; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;posixstr = &amp;quot;CET-1CEST-2,M3.5.0/02:00, M10.5.0/03:00&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;spaintz = tz.tzstr(posixstr) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print datetime.datetime.now(spaintz).ctime( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;在不同时区中转换也是可以的,而且在生活中可能经常遇到.比如,让我们找出下一界奥林匹克运动会开幕的时间,以西班牙时间为准: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;chinatz = tz.tzoffset(&amp;quot;China&amp;quot;, 60*60*8) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;olympicgames = datetime.datetime(2008, 8, 8, 20, 0, tzinfo=chinatz) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print olympicgames.astimezone(spaintz)&lt;/span&gt;&lt;br&gt;&lt;br&gt;前面使用的那个神秘的posixstr是一种使用OPSIX方式来表示时区的字符串,现在在西班牙使用.这个字符串提供了标准和夏令时时区(CST,CEST)的名称,他们的偏移量(UTC+1,UTC+2),以及夏令时开始和结束的时间(3月最后一个周日的早上2点,8月的最后一个周日早上3点).我们可以判断DST时区来保证它们正确: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;assert spaintz.tzname(datetime.datetime(2004, 03, 28, 1, 59)) == &amp;quot;CET&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;assert spaintz.tzname(datetime.datetime(2004, 03, 28, 2, 00)) == &amp;quot;CEST&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;assert spaintz.tzname(datetime.datetime(2004, 10, 31, 1, 59)) == &amp;quot;CEST&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;assert spaintz.tzname(datetime.datetime(2004, 10, 31, 2, 00)) == &amp;quot;CET&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;这上面的assert都应该能通过.&lt;br&gt;注意到尽管回到标准时间是早上3点,可是上面还是按照2点来写,是因为2点和3点的时间差, 是很模糊的.那个2点重复了2次:一次是标准时间,一次夏令时.就当前来说,使用Python的datetime不能区分二者,所以建议你保存UTC时间实例,来进行时区转换. &lt;br&gt;为了在中国和西班牙间进行时区转换,我们使用tzoffset来表示中国时间比UTC早8个小时,注意datetime对象是怎样被建立的,即使是本地时间,也要作这样的转换.如果你没有使用时区信息来创建datetime对象,你将会获得异常:ValueError: astimezone( ) cannot be applied to a naive datetime. datetime对象在创立的时候,总是默认没有时区信息,除非你显式的给出时区信息.为此 ,dateutil提供了tzlocal类型,它用来表示本地时区的时间.&lt;br&gt;除了目前我们所看到的类型外,dateutil也提供tzutc,它用于创建UTC时间对象.tzfile,它允许使用标准时间二进制文件.tzical,它用于创建iCalender时区对象.当然,还有很多别的类型.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-6808500405827851060?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/6808500405827851060/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=6808500405827851060' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6808500405827851060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6808500405827851060'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-39.html' title='Python Cookbook 3.9 转换时区'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-3360289902434469922</id><published>2007-08-14T15:43:00.001+08:00</published><updated>2007-08-28T13:53:39.848+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.8 判断夏令时是否有效</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要知道当前的夏令时在你的时区是否有效.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;很容易想到使用time.daylight方法,但实际上不是的:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import time &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def is_dst( ): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return bool(time.localtime( ).tm_isdst)&lt;/span&gt;&lt;br&gt;&lt;br&gt;在我处于的时区中,time.daylight总是1,因为time.daylight表示一年中有些夏令时存在.并不是说判断今天是否是夏令时.&lt;br&gt;然而调用time.localtime ,仅当当天是夏令时后,才返回1,否则返回0.本节将这个调用进行的封装,并返回内建的bool类型,你也可以使用time.localtime()[-1]来访问这个值,但是使用tm_isdst更可读一些.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;夏令时，又称"日光节约时制"（Daylight Saving Time），是一种为节约能源而人为规定地方时间的制度，在这一制度实行期间所采用的统一时间称为"夏令时"。一般在天亮早的夏季人为将时间提前一小时， 可以使人早起早睡，减少照明量，以充分利用光照资源，从而节约照明用电。各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令 时。 &lt;br&gt; &lt;br&gt;据说最早建议使用夏时制的是本杰明・富兰克林，他在任美国驻法国大使期间，由于习惯于当时美国农村贵族的早睡早起生活，早上散步时看到法国人10 点才起床，夜生活过到深夜。于是他在1784年的一期《巴黎杂志》上发表了一篇文章，说法国人的生活习惯浪费了大好的阳光，建议法国人早睡早起，说每年可 以节约6千4百万磅蜡烛。但他当时并没有建议实行夏时制，因为当时根本还没有统一的时区划分。不过夏时制在英语里就是"节约阳光时间"的意思。 &lt;br&gt; &lt;br&gt;直到1907年，一位英国建筑师威廉・维莱特（William Willett）才正式向英国议会提出夏时制的设想，主要是为了节省能源和提供更多的时间用来训练士兵，但议会经过辩论没有采纳。 &lt;br&gt; &lt;br&gt;1916年，德国首先实行夏时制，英国因为怕德国会从中得到更大的效益，因此紧跟着也采取了夏时制，夏时制节约了约15%的煤气和电力，但为了弥 补损失，电力和煤气公司也将价格提高了15%。法国不久也效仿实行。1917年，俄罗斯第一次实行了夏令时，但直到1981年才成为一项经常性的制度。 1918年，参加了第一次世界大战的美国也实行了夏时制，但战后立即取消了。 &lt;br&gt; &lt;br&gt;1942年，第二次世界大战期间，美国又实行了夏时制，1945年战争结束后取消。1966年，美国重新实行夏时制。欧洲大部分国家从1976年，即第四次中东战争导致首次石油危机3年后（1973年）开始实行夏时制。 &lt;br&gt; &lt;br&gt;根据联合国欧洲经济委员会的建议，从1996年起夏令时的有效期推迟到10月份的最后一个星期日。&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-3360289902434469922?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/3360289902434469922/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=3360289902434469922' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3360289902434469922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3360289902434469922'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-38.html' title='Python Cookbook 3.8 判断夏令时是否有效'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-1491522398571775821</id><published>2007-08-14T15:29:00.001+08:00</published><updated>2007-08-28T13:53:39.849+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.7 解析时间数据</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你的程序需要接收时间数据,而这些数据不是按照标准的datetime数据格式&amp;quot;yyyy,mm,dd&amp;quot;来组织的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;第三方库dateutil的dateutil.parse提供了简便的解决方案:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import datetime &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import dateutil.parser &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def tryparse(date): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # dateutil.parser needs a string argument: let&amp;#39;s make one from our &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # `date&amp;#39; argument, according to a few reasonable conventions...: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; kwargs = {&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # assume no named-args &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if isinstance(date, (tuple, list)): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; date = &amp;#39; &amp;#39;.join([str(x) for x in date])&amp;nbsp;&amp;nbsp;&amp;nbsp; # join up sequences &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; elif isinstance(date, int): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; date = str(date)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # stringify integers &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; elif isinstance(date, dict): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; kwargs = date&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # accept named-args dicts &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; date = kwargs.pop(&amp;#39;date&amp;#39;)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # with a &amp;#39;date&amp;#39; str &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parsedate = dateutil.parser.parse(date, **kwargs) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Sharp %r -&amp;gt; %s&amp;#39; % (date, parsedate) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; except ValueError: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parsedate = dateutil.parser.parse(date, fuzzy=True, **kwargs) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Fuzzy %r -&amp;gt; %s&amp;#39; % (date, parsedate) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; except Exception, err: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Try as I may, I cannot parse %r (%s)&amp;#39; % (date, err) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;quot;_ _main_ _&amp;quot;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; tests = ( &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;January 3, 2003&amp;quot;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # a string &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (5, &amp;quot;Oct&amp;quot;, 55),&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # a tuple &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Thursday, November 18&amp;quot;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # longer string without year &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;7/24/04&amp;quot;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # a string with slashes &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;24-7-2004&amp;quot;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # European-format string &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;#39;date&amp;#39;:&amp;quot;5-10-1955&amp;quot;, &amp;quot;dayfirst&amp;quot;:True}, # a dict including the kwarg &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;5-10-1955&amp;quot;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # dayfirst, no kwarg &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 19950317,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # not a string &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;11AM on the 11th day of 11th month, in the year of our Lord 1945&amp;quot;, &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for test in tests:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # testing date formats &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tryparse(test)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # try to parse&lt;/span&gt;&lt;br&gt;&lt;br&gt;dateutil.parse可以工作于多种时间格式.本节演示了一部分的用法.那个解析器可以解析英语国家的月份表示和2或4位的年表示法.当你给它传递的参数没有命名的时候 ,它默认使用&amp;quot;mm-dd-yy&amp;quot;,如果发现解析后没有意义,比如例子中给出的&amp;quot;24-7-2004&amp;quot;,解析器会尝试&amp;quot;dd-nn-yy&amp;quot;,最后,它会尝试&amp;quot;yy-mm-dd&amp;quot;.如果命名参数给出了,它会按照命名参数进行解析.&lt;br&gt;本节的测试代码包含了一些可能会遇到的边界条件,比如以元组的形式传递参数,或者以整数的形式,甚至一个短语.为了测试关键字,tryparse函数还允许字典作为参数,可以将键为date的值转换为时间对象,其余的作为函数的命名参数. &lt;br&gt;dateutil.parse可以做模糊解析.给出一些提示来让它解析,比如,小时(本节中使用了AM).对于商业级代码,你最好避免模糊解析,做一些预处理,并对解析结果进行检查.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-1491522398571775821?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/1491522398571775821/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=1491522398571775821' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1491522398571775821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1491522398571775821'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-37.html' title='Python Cookbook 3.7 解析时间数据'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-6189428571322925962</id><published>2007-08-13T11:42:00.000+08:00</published><updated>2007-08-28T13:53:39.849+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.6 自动查询假日信息</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;每个国家,地区,民族甚至是同一个公司的假期设置都不尽相同.你需要自动查出在两个日期间假期的个数.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;在两个日期之间,可能有日期不定的节日,比如美国的复活节和劳动节,还有根据复活节计算的节日,比如礼节日(Boxing Day),或者有固定日期的节日, 比如圣诞节.甚至你们公司自己的节日(比如老板的生日).你都可以使用datetime和第三方包util来处理这些情况.&lt;br&gt;一个比较方便的方法是将不同的情况分别处理,封装在不同的函数里: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;from dateutil import rrule, easter &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;try: set &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;except NameError: from sets import Set as set &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def all_easter(start, end): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # return the list of Easter dates within start..end &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; easters = [easter.easter(y)&amp;nbsp; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for y in xrange(start.year, end.year+1)] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [d for d in easters if start&amp;lt;=d&amp;lt;=end] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def all_boxing(start, end): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # return the list of Boxing Day dates within start..end &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; one_day = datetime.timedelta(days=1) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; boxings = [easter.easter(y)+one_day&amp;nbsp; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for y in xrange(start.year, end.year+1)] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [d for d in boxings if start&amp;lt;=d&amp;lt;=end] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def all_christmas(start, end): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # return the list of Christmas Day dates within start..end &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; christmases = [datetime.date(y, 12, 25)&amp;nbsp; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for y in xrange(start.year, end.year+1)] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [d for d in christmases if start&amp;lt;=d&amp;lt;=end] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def all_labor(start, end): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # return the list of Labor Day dates within start..end &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; labors = rrule.rrule(rrule.YEARLY, bymonth=9, byweekday=rrule.MO(1), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dtstart=start, until=end) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [d.date( ) for d in labors]&amp;nbsp;&amp;nbsp; # no need to test for in-between here &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def read_holidays(start, end, holidays_file=&amp;#39;holidays.txt&amp;#39;): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # return the list of dates from holidays_file within start..end &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; holidays_file = open(holidays_file) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; except IOError, err: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;cannot read holidays (%r):&amp;#39; % (holidays_file,), err &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [&amp;nbsp; ] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; holidays = [&amp;nbsp; ] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; for line in holidays_file: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # skip blank lines and comments &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if line.isspace( ) or line.startswith(&amp;#39;#&amp;#39;): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; continue &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # try to parse the format: YYYY, M, D &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; y, m, d = [int(x.strip( )) for x in line.split(&amp;#39;,&amp;#39;)] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; date = datetime.date(y, m, d) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; except ValueError: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # diagnose invalid line and just go on &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;Invalid line %r in holidays file %r&amp;quot; % ( &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; line, holidays_file) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; continue &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if start&amp;lt;=date&amp;lt;=end: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; holidays.append(date) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; holidays_file.close( ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return holidays &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;holidays_by_country = { &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # map each country code to a sequence of functions &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;US&amp;#39;: (all_easter, all_christmas, all_labor), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;IT&amp;#39;: (all_easter, all_boxing, all_christmas), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;} &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def holidays(cc, start, end, holidays_file=&amp;#39; holidays.txt&amp;#39;): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # read applicable holidays from the file &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; all_holidays = read_holidays(start, end, holidays_file) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # add all holidays computed by applicable functions &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; functions = holidays_by_country.get(cc, ( )) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for function in functions: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; all_holidays += function(start, end) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # eliminate duplicates &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; all_holidays = list(set(all_holidays)) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # uncomment the following 2 lines to return a sorted list: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # all_holidays.sort( ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # return all_holidays &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return len(all_holidays)&amp;nbsp;&amp;nbsp;&amp;nbsp; # comment this out if returning list &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test_file = open(&amp;#39;test_holidays.txt&amp;#39;, &amp;#39;w&amp;#39;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test_file.write(&amp;#39;2004, 9, 6\n&amp;#39;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test_file.close( ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; testdates = [ (datetime.date(2004, 8,&amp;nbsp; 1), datetime.date(2004, 11, 14)), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (datetime.date(2003, 2, 28), datetime.date(2003,&amp;nbsp; 5, 30)), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (datetime.date(2004, 2, 28), datetime.date(2004,&amp;nbsp; 5, 30)), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def test(cc, testdates, expected): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (s, e), expect in zip(testdates, expected): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;total holidays in %s from %s to %s is %d (exp %d)&amp;#39; % ( &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cc, s, e, holidays(cc, s, e, test_file.name), expect) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test(&amp;#39;US&amp;#39;, testdates, (1,1,1) ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test(&amp;#39;IT&amp;#39;, testdates, (1,2,2) ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import os &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  os.remove(test_file.name)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;在我工作的公司里面,有几个工会,公司的节假日由几个工会协商制定.另外,我需要将下雪天和发布产品的日期作为&amp;quot;官方&amp;quot;节假日.为了处理各种情况,比较方便的方法是将不同类型的节假日放在不同的函数中处理,比如上例中我们对all_Easter和all_labor的处理.对于各种不同的情况都有列出 ,所以你很容易写出自己的来.&lt;br&gt;尽管半开区间(区间左边界被包含而右边界不包含)是Python的标准(因为它有更好的灵活性以及能避免用户的一些使用问题),本节使用全封闭区间来处理.不幸的是,无论时间区间多明确的给出,dateutil还是那样工作.所以我们的选择很明显.&lt;br&gt;每个函数确保满足你的要求的日期才被返回:一个datetime.date实例列表被传递给函数,而且它们都是处于给定日期区间内的.比如,在all_labor里面,我们强制将使用dateutil的rrule的datetime.datetime类型由转换为datetime.date类型后返回 .&lt;br&gt;有些公司可能仅仅一次设置某些天为假期(比如下雪天),我们可以使用一个文本文件来保存这些数据.在我们的例子中,read_holidays函数用于处理和分析这个文件,你可以将这一部分代码用&amp;quot;fuzzy&amp;quot;日期分析器来处理.&lt;br&gt;如果你在程序运行过程中可能会多次查询,最好将读文件部分优化为一次处理,然后将内容保存在列表中以便后面使用.然而,&amp;quot;不成熟的优化是程序罪恶的根源&amp;quot;记得Knuth的话吗?避免使用哪怕最&amp;quot;显然&amp;quot;的优化,也要保证程序的清晰和灵活,假设我们的程序是运行在交互式环境中,每次读取文件避免了判断文件是否被修改的麻烦. &lt;br&gt;因为不同的国家的节假日不同,所以本节的代码也提供了一个holidays_by_country的字典.你可以根据不同的需要来更新这个字典.需要注意的是这个字典允许不同的生成器函数调用,依据你给定的国家代码.如果你的国家有很多州,你很容易创建一个基于州信息的字典,传递州编号来替代国家编号.holidays函数会调用合适的函数,并组合结果,去除重复数据,并返回结果的个数.当然,你也可以返回结果的列表,仅仅需要去掉上面代码中的两行注释就可以了. &lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-6189428571322925962?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/6189428571322925962/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=6189428571322925962' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6189428571322925962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6189428571322925962'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-36.html' title='Python Cookbook 3.6 自动查询假日信息'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-7657362366294573573</id><published>2007-08-10T13:56:00.001+08:00</published><updated>2007-08-28T13:53:39.849+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.5 计算两日期间的工作日数</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要计算两个日期间的工作日数,而不是天数.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;因为对于周末的定义,每个国家,地区甚至公司都不同.所以没有内建的函数来完成这个需求,不过使用datetutil和datetime,可以很方便的实现这个需求.&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; from dateutil import rrule&amp;nbsp; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def workdays(start, end, holidays=0, days_off=None): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if days_off is None: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; days_off = 5, 6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # default to: saturdays and sundays &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; workdays = [x for x in range(7) if x not in days_off] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; days = rrule.rrule(rrule.DAILY, dtstart=start, until=end, &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byweekday=workdays) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return days.count( ) - holidays &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# test when run as main script &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; testdates = [ (datetime.date(2004, 9, 1), datetime.date(2004, 11, 14), 2), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (datetime.date(2003, 2, 28), datetime.date(2003, 3, 3), 1), ] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def test(testdates, days_off=None): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for s, e, h in testdates: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;total workdays from %s to %s is %s with %s holidays&amp;#39; % ( &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; s, e, workdays(s, e, h, days_off), h) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test(testdates) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test(testdates, days_off=[6])&lt;/span&gt;&lt;br&gt;&lt;br&gt;这个程序是我用Python写的第一个程序:我需要知道员工培训的具体日子,当给定两个日期的情况下.这个问题在Python2.2前是比较难办的,现在有了datetime和dateutil,变得非常简单了. &lt;br&gt;函数workdays首先给变量day_off设置了默认值(除非显式的给它赋值).它表示在一周中我们休息的日子.在我的公司中,每个人休息的日子是不同的,但一般情况都不会多于工作的日子,所以对我们来说,修改休息日比修改工作日更好一些.我把它作为函数的一个参数,这样在我需要另外的休息日的时候,可以简单的作为参数传递进来.接下来,函数创建了工作日的列表,里面不包含休息日.剩下要做的就是计算了.&lt;br&gt;在本节中做最多工作的是一个实例,days, 来自dateutil.rrule类.类rrule可以用来产生很多种不同的尺子.在本例中,我传递了常用的rrule.DAILY,还需要给出起始时间和终止时间,而且都是datetime.date类型.然后,我们只要调用days.count来计算其中的天数.&lt;br&gt;你可以自己定义周末:只要给day_off里面添加值就好了.在本节中,我们使用惯例的周六和周日作为周末,加入,你的公司是4工作日制,从周二到周五,你可以使用day_off=(5,6,0),只要以可以遍历的形式传递就好了,比如列表和元组. &lt;br&gt;一个简单的功能加强是自动判断给出的起始日和终止日是否是周末,如果是的话,自动修改day_off的值.更多的功能添加可以是加入病假日,或者查询休假日,而不是需要自己给出每一个休假日.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-7657362366294573573?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/7657362366294573573/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=7657362366294573573' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7657362366294573573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7657362366294573573'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-35.html' title='Python Cookbook 3.5 计算两日期间的工作日数'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-7459390137826468847</id><published>2007-08-08T11:47:00.001+08:00</published><updated>2007-08-28T13:53:39.850+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.4 计算播放歌曲的时长</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求：&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要知道播放列表中歌曲的总时长。&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论：&lt;/span&gt;&lt;br&gt;&lt;br&gt;使用datetime模块的内建函数sum来作统计工作：&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def totaltimer(times): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; td = datetime.timedelta(0)&amp;nbsp;&amp;nbsp;&amp;nbsp; # initial value of sum (must be a timedelta) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; duration = sum([ &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; datetime.timedelta(minutes=m, seconds=s) for m, s in times], &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; td) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return duration &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _== &amp;#39;_ _main_ _&amp;#39;:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # test when module run as main script &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; times1 = [(2, 36),&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # list containing tuples (minutes, seconds) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (3, 35), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (3, 45),] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; times2 = [(3, 0), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (5, 13), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (4, 12), &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (1, 10),] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert totaltimer(times1) == datetime.timedelta(0, 596) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert totaltimer(times2) == datetime.timedelta(0, 815) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print (&amp;quot;Tests passed.\n&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;First test total: %s\n&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Second test total: %s&amp;quot; % ( &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; totaltimer(times1), totaltimer(times2)))&lt;/span&gt;&lt;br&gt;&lt;br&gt;当我工作的时候，会播放一个很大的播放列表。我想知道自己选择的歌曲的总时长，而不是重新建立一个播放列表，所以写下了这个脚本。&lt;br&gt;一个datetime.timedelta对象一般返回两个给定的datetime对象的差值 。当然，你也可以创建自己的timedelta对象来衡量任意之间的差值。在在这里，我们需要计算时长，所以timedelta正是我们需要的。&lt;br&gt;datetime.timedelta函数可以有很多可选参数：days,seconds,microseconds,milliseconds,minutes,hours,weeks.所以，创建对象的时候，你需要使用命名参数，否则自己会被搞混的。如果你仅仅使用了datetime.timedelta(m,n),而没有使用命名参数，该类会认为m表示days，n表示seconds，那真的会产生很奇怪的结果。 &lt;br&gt;使用内建的sum函数来计算一个列表中的值比如timedelta，你需要给sum传递第二个参数来表示初始值，否则它会初始为0，整数0，而你会得到一个异常，因为将整数和timedelta相加。列表中的对象需要支持数字加法。（strings是没有加法的，所以，不要用sum来加string或者别的列表！）。在Python2.4中，对于sum的第一个参数，我们可以用生成表达式来替换［］，这样我们可以方便的处理具有大数据量的列表。&lt;br&gt;为了测试目的，我自己手动创建了一个列表，里面的元组表示分钟和秒。这个脚本可以修改为加强版，比如支持更多的格式（如mm:ss）或者直接从文件中读取数据。 &lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;相关说明：&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;sum(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sum(sequence, start=0) -&amp;gt; value&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Returns the sum of a sequence of numbers (NOT strings) plus the value &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; of parameter &amp;#39;start&amp;#39;.&amp;nbsp; When the sequence is empty, returns start.&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-7459390137826468847?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/7459390137826468847/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=7459390137826468847' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7459390137826468847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7459390137826468847'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-34.html' title='Python Cookbook 3.4 计算播放歌曲的时长'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-138361456419197319</id><published>2007-08-08T11:23:00.001+08:00</published><updated>2007-08-28T13:53:39.850+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.3 在一个时间范围内计算时间差</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求：&lt;/span&gt;&lt;br&gt;&lt;br&gt;给定两个时间，你需要计算它们间相差几周。&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论：&lt;/span&gt;&lt;br&gt;&lt;br&gt;同样的，标准库中的datetime和第三方包dateutil都是十分方便的（尤其是dateutil的rrule.count方法）.当引入和合适的包后，工作变得异常简单：&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;from dateutil import rrule &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def weeks_between(start_date, end_date): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; weeks = rrule.rrule(rrule.WEEKLY, dtstart=start_date, until=end_date) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return weeks.count( )&lt;/span&gt;&lt;br&gt;&lt;br&gt;函数weeks_between使用起始和终止时间作为参数，初始化一个尺子来测量它们之间的差值，然后返回。写代码比描述起来还要方便。这个方法仅仅返回一个整数，比如，8天被认为是2周。很容易来测试一下这个代码： &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _==&amp;#39;_ _main_ _&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; starts = [datetime.date(2005, 01, 04), datetime.date(2005, 01, 03)] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end = datetime.date(2005, 01, 10) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for s in starts: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; days = rrule.rrule(rrule.DAILY, dtstart=s, until=end).count( ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;%d days shows as %d weeks &amp;quot;% (days, weeks_between(s, end))&lt;/span&gt;&lt;br&gt;&lt;br&gt;测试输出如下：&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; 7 days shows as 1 weeks &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;8 days shows as 2 weeks&lt;/span&gt;&lt;br&gt;&lt;br&gt;没有必要为尺子取一个名字，如果你不想改变函数体，比如改成一条语句：&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;return rrule.rrule(rrule.WEEKLY , dtstart=start_date, until=end_date).count( )&lt;/span&gt;&lt;br&gt;&lt;br&gt;也是没有问题的。我个人喜欢给尺子命名因为觉得它有些奇怪，不过它是如此的强大以至于我不能离开它了。&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-138361456419197319?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/138361456419197319/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=138361456419197319' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/138361456419197319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/138361456419197319'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-33.html' title='Python Cookbook 3.3 在一个时间范围内计算时间差'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-2777956215231742578</id><published>2007-08-07T13:53:00.001+08:00</published><updated>2007-08-28T13:53:39.850+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.2 查找最近的星期五</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要知道最近星期五的日期(或者是今天,如果今天是星期五),然后用特定的格式输出.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你可以使用datetime模块来实现这个需求:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime, calendar &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;lastFriday = datetime.date.today( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;oneday = datetime.timedelta(days=1) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;while lastFriday.weekday  ( ) != calendar.FRIDAY:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; lastFriday -= oneday&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print lastFriday.strftime (&amp;#39;%A, %d-%b-%Y&amp;#39;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# emits, e.g.: Friday, 10-Dec-2004&lt;/span&gt;&lt;br&gt;&lt;br&gt;上面的代码方便的实现了查找最近的星期五,并用特定的格式输出,无论这个周五是不是处于同一月,甚至同一年.在这个例子里面,我们查找最近的星期五.星期五的整数表示是4   ,但是为了避免使用这个&amp;quot;魔幻数字&amp;quot;,我们使用Python标准库的calendar模块中的calendar.FRIDAY来表示(当然,我敢确定,它的值也是4).我们设置了一个变量叫做lastFriday,它保存今天的日期,然后让它递减,直到它的weekday值为4.&lt;br&gt;一旦我们找到了需要的日期,格式化输出就变得异常简单,使用datetime.date的strftime方法就可以了.&lt;br&gt;另一个更简洁的做法是使用内建的常量datetime.date.resolution来替代datetime.timedelta来表示一天   .&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime, calendar&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;lastFriday = datetime.date.today( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;while lastFriday.weekday( ) != calendar.FRIDAY:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; lastFriday -= datetime.date.resolution&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;print lastFriday.strftime(&amp;#39;%d-%b-%Y&amp;#39;)&lt;/span&gt;&lt;br&gt;  &lt;br&gt;类属性datetime.date.resolution表示了一天的时间.然而,resolution可能会混淆你,因为它随着不同的datetime模块其值也是不同的.对于date模块,timedelta(day=1),但是对于time和datetime类,它们的timedelta(microseconds=1),你可以进行混合匹配,但容易搞混.使用本节开始的方法,会更通用一些,也不容易搞混.而且,怎么说它也是最Python的写法(那可是官方版本). &lt;br&gt;一个重要的需要加强的地方是我们不需要使用循环,一次次的减少时间.我们可以一次性得到目标,使用算数计算就OK了:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime, calendar&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;today = datetime.date.today ( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;targetDay = calendar.FRIDAY&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thisDay = today.weekday( )&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;deltaToTarget = (thisDay - targetDay) % 7 &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;lastFriday = today - datetime.timedelta(days=deltaToTarget)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print  lastFriday.strftime(&amp;#39;%d-%b-%Y&amp;#39;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;要始终追求最清晰的方式,而不是效率.记住Hoare的名言:&amp;quot;在编程中不成熟的优化是罪恶的根源&amp;quot;.让我们看看为什么优化是不成熟的.&lt;br&gt;用最普通的装备在一个4年的老机器上,跑着linux和Python2.4 ,用本节开始的方法,用时18.4毫秒,用最后的方法,用时10.1毫秒.&lt;br&gt;在你的一生中,并不会总去计算上周5是什么时候,对吧.接下来...(一些证明词).&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;weekday(...)&lt;/span&gt;&lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; Return the day of the week represented by the date.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Monday == 0 ... Sunday == 6&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;strftime(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; format -&amp;gt; strftime() style string. &lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-2777956215231742578?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/2777956215231742578/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=2777956215231742578' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2777956215231742578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2777956215231742578'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-32.html' title='Python Cookbook 3.2 查找最近的星期五'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-7806422090024609592</id><published>2007-08-07T13:06:00.001+08:00</published><updated>2007-08-28T13:53:39.850+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.1 计算昨天和明天</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要得到今天的日期,然后计算昨天的或明天的日期.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;任何需要计算时间&amp;quot;变化&amp;quot;或&amp;quot;差值&amp;quot;的时候,请考虑使用timedelta:&lt;br&gt; &lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import datetime&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;today = datetime.date.today( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; yesterday = today - datetime.timedelta(days=1)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;tomorrow = today + datetime.timedelta(days=1)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; print yesterday, today, tomorrow&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;#emits: 2004-11-17 2004-11-18 2004-11-19&lt;/span&gt;&lt;br&gt;&lt;br&gt;本节提出的问题在Python邮件列表里面经常被问道.当我们第一次面对这个问题的时候,直觉的想法是写下代码如:yesterday = today-1,它会报出异常: TypeError: unsupported operand type(s) for -: &amp;#39; datetime.date&amp;#39; and &amp;#39;int&amp;#39;.&lt;br&gt;有些人认为这是Python的一个bug,它们期望Python能猜测用户的目的.然而,Python简单和强大的一个信条就是:遇到不清楚的时候,拒绝猜测.假如要尝试猜测的话,必须要认真考虑你指的一天,一秒,还是一年.&lt;br&gt;Python不会猜测你的需求,而是让你表达的更明确,如果你希望给一个时间减去一天,就显示的写出这样的代码.如果,你希望给一个时间加上一秒,你可以使用timedelta和datetime.datetime对象 ,然后可以使用相同的语法来实现.像这样,对于每一个你希望完成的任务,都会只有一个明确的方式来完成.这样做也会增加很多灵活性,而且不让问题变得更复杂.看看下面的脚本:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; anniversary = today + datetime.timedelta(days=365)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # add 1 year&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; print anniversary&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;2005-11-18&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;gt;&amp;gt;&amp;gt; t = datetime.datetime.today( )&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # get right now&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; t&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;datetime.datetime(2004, 11, 19, 10, 12, 43, 801000)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; t2 = t + datetime.timedelta(seconds=1)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # add 1 second &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; t2&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;datetime.datetime(2004, 11, 19, 10, 12, 44, 801000) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; t3 = t + datetime.timedelta(seconds=3600)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # add 1 hour&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;gt;&amp;gt;&amp;gt; t3&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;datetime.datetime(2004, 11, 19, 11, 12, 43, 801000)&lt;/span&gt;&lt;br&gt;&lt;br&gt;请记住,如果你爱好对时间进行计算,第三方包,比如dateutil和经典的mx.Datetime都很适合,如:&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;from dateutil import relativedelta &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;nextweek = today + relativedelta.relativedelta(weeks=1)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;print nextweek&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;#emits: 2004-11-25&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;然而,&amp;quot;总是用最简单的方式来工作&amp;quot;,为了简单起见, 用datetime.timedelta就足够了.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;class timedelta(__builtin__.object)&lt;/span&gt;&lt;br&gt;&amp;nbsp;Difference between two datetime values.&lt;br&gt;&lt;br&gt;支持的操作有:&lt;br&gt; abs,四则运算及常见比较.&lt;br&gt;&lt;br&gt;&amp;nbsp;Data descriptors defined here:&lt;br&gt;&lt;br&gt;&amp;nbsp;days&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of days.&lt;br&gt;&lt;br&gt;&amp;nbsp;microseconds&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of microseconds (&amp;gt;= 0 and less than 1 second).&lt;br&gt;&lt;br&gt;&amp;nbsp;seconds&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Number of seconds (&amp;gt;= 0 and less than 1 day). &lt;br&gt;&lt;br&gt;&amp;nbsp;----------------------------------------------------------------------&lt;br&gt;&amp;nbsp;Data and other attributes defined here:&lt;br&gt;&lt;br&gt;&amp;nbsp;max = datetime.timedelta(999999999, 86399, 999999)&lt;br&gt;&lt;br&gt;&amp;nbsp;min = datetime.timedelta(-999999999) &lt;br&gt;&lt;br&gt;&amp;nbsp;resolution = datetime.timedelta(0, 0, 1)&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-7806422090024609592?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/7806422090024609592/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=7806422090024609592' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7806422090024609592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7806422090024609592'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-31.html' title='Python Cookbook 3.1 计算昨天和明天'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-5883573148277042522</id><published>2007-08-06T11:23:00.001+08:00</published><updated>2007-08-28T13:53:39.850+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python Cookbook 3.0 Python时间和货币概述</title><content type='html'>&lt;span style="font-weight: bold;"&gt;概述:&lt;/span&gt;&lt;br&gt;&lt;br&gt;今天,上周末,明年.这些名词听起来很平常.你可能曾经感觉到奇怪,也许仅仅一次,关于时间是如何深刻的影响着我们的生活.时间的概念围绕着我们,它也大量的存在于软件工程中.任何一个简单的程序都可能要处理时间戳,延迟,超时,速度测量,日历等等.如果一个语言拥有&amp;quot;Batteries Included&amp;quot;(便携电池)特性,将会非常方便.Python的标准库为这些应用程序提供了稳定的支持 ,也可以从第三方包中获得更多的支持. &lt;br&gt;在计算机处理中,货币问题是另外一个比较有趣的话题,因为它和我们的生活息息相关.Python2.4后引入了对带小数点数的支持,使得Python成为要处理小数点的一个不错的选择,而且它避免使用浮点数.&lt;br&gt;本章主要讨论这两个方面,时间和货币.对于传统的说法,其实文章只介绍了一个问题,因为大家都知道:&amp;quot;时间就是金钱!&amp;quot;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;时间模块:&lt;/span&gt; &lt;br&gt;&lt;br&gt;Python标准库的time模块使得Python应用程序能很方便的使用Python所运行平台上的时间函数.你的系统文档中的C语言库文档也是很有用的 ,其它一些平台也会对Python有用.&lt;br&gt;time模块中最常用的函数就是获得当前时间:time.time.这个函数的返回值有些隐晦难懂:它是一个浮点数,表示从一个叫做epoch的固定时间到当前时间的秒数.那个时间可能因为系统的不同而不同,不过大多数系统都是1970年1月1号的午夜.&lt;br&gt;要判断你的系统使用什么epoch,使用下面的代码:&lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;gt;&amp;gt;&amp;gt; import time&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; print  time.asctime(time.gmtime(0))&lt;/span&gt;&lt;br&gt;&lt;br&gt;请注意我们传递了参数0给time.gmtime函数,表示从epoch后过0秒,time.gmtime将任何时间戳(从epoch到现在的秒数)转换为一个元组,该元组用人们可以理解的方式表示时间,而且不做时区转换(GMT表示格林威治时间,UTC表示国际标准时间).你也可以传递一个时间戳给time.localtime,它将使用本地的时区来转换时间.&lt;br&gt;需要主意二者的区别,如果你的时间戳已经是对应于本地时区了,, 那么再把它传递给time.localtime将不会返回期望的值,除非你的时区恰好和UTC一致.&lt;br&gt;下面提供一个分解时间元组的方法:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;year, month, mday, hour, minute, second, wday, yday = time.localtime( )&lt;/span&gt;&lt;br&gt;&lt;br&gt;这种方法虽然有效,但是不提倡使用,因为它很不美观.这样的写法可以完全摒弃 ,因为你可以使用跟可读的字段来获取元素的值,比如获取当前月的信息:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;time.localtime( ).tm_mon&lt;/span&gt;&lt;br&gt;&lt;br&gt;请注意我们调用localtime的时候并没有传递任何参数,当我们使用localtime,gmtime或asctime的时候,如果不传递任何参数,它们会默认使用当前时间.&lt;br&gt;在time模块中比较有用的两个方法是strtime和strptime,前者能从一个时间元组获得字符串, 而后者通过一个字符串获得一个时间元组.两个方法都接收格式化字符串为参数,从而获得你需要的字符串结果.关于传递的格式化字符串的具体信息,可以参见&lt;a href="http://docs.python.org/lib/module-time.html"&gt;http://docs.python.org/lib/module-time.html&lt;/a&gt;.&lt;br&gt;在time模块中最后一个比较重要的方法是time.sleep函数,它可以让Python程序延迟.尽管函数POSIX计数器部分只接受整数为参数 ,Python支持了小数并可以实现半秒,如:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for i in range(10):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; time.sleep(0.5)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;Tick!&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;这段代码将执行5秒钟,每秒输出2个Tick.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;时间和日期对象:&lt;/span&gt;&lt;br&gt;&lt;br&gt;尽管time模块十分强大,Python标准库还提供了datetime模块,它里面提供的类型更好的抽象了日期和时间的概念,它的类型包括:time,date, datetime.它们构造的方法相同:&lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; today = datetime.date.today( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; birthday = datetime.date (1977, 5, 4)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #May 4&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; currenttime = datetime.datetime.now( ).time( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp; lunchtime = datetime.time(12, 00)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; now = datetime.datetime.now( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp; epoch = datetime.datetime(1970, 1, 1)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; meeting = datetime.datetime(2005, 8, 3, 15, 30)&lt;/span&gt;&lt;br&gt;&lt;br&gt;同时,这些对象也提供了很多方便的方法来访问它的属性.下面的语句创建了date类型的实例 ,表示今天,然后获取明天的今天,最后以点分格式输出:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; today = datetime.date.today( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; next_year = today.replace(year=today.year+1 ).strftime(&amp;quot;%Y.%m.%d&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp; print next_year&lt;/span&gt;&lt;br&gt;&lt;br&gt;注意是怎样增加一年的,使用了replace方法,直接给time实例复制是很方便的,而它的属性确实不可修改的(这样的好处是,你可以把属性看成字典来访问),所以要创建新实例next_year. &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; import datetime&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; NewYearsDay = datetime.date(2005, 01, 01)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; NewYearsEve = datetime.date(2004, 12, 31)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; oneday = NewYearsDay - NewYearsEve&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; print oneday&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;1 day, 0:00:00&lt;/span&gt;&lt;br&gt;&lt;br&gt;一个timedelta实例在内部是使用天,秒和毫秒来表示的,但你可以通过传递任意形式的时间参数来构造timedelta,比如分钟,小时, 星期等.别的形式的时间差默认是不支持的,因为容易它的操作和结果可能产生歧义(有第三方包支持这些特征,如dateutil).&lt;br&gt;datetime可以称为小心谨慎的设计,它不会实现不明确的任务,或者和平台依赖性太强的任务,和别的模块的实现思路一样.&lt;br&gt;该模块另一个设计的特点是时区的支持.尽管datetime提供了查询和设置时区的功能,没有外界类继承tzinfo类的话还是用处不大.有两个第三方扩展提供了对时区的支持,如dateutil和pyTZ. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;十进制数:&lt;/span&gt;&lt;br&gt;&lt;br&gt;decimal是Python标准库的一部分,自Python2.4后添加入的.它将十进制算数引入了Python.有了decimal,我们现在有了十进制小数类型,它同时保证了精度和浮点数的特征.让我们先来介绍三个概念:&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;十进制小数类型(decimal numeric) &lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 数字不是用二进制来存储的,是用十进制数字存储的.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;定点小数&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 数字的小数位数是固定的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;浮点小数&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 小数点没有固定.(换一个说法:数字的总位数是固定的,但小数点后面的位数是不固定的) &lt;br&gt;&lt;br&gt;这样的数据类型有很多用处(最大的用处就是计算货币),尤其是decimal.Decimal提供了比float更多的更高级的方法,最主要的好处是用户输入的数字能完整的保留精度(也就是数,使用二进制保存的浮点数不能保证有些数字的精度):&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; import decimal&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; 1.1&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;1.1000000000000001&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;gt;&amp;gt;&amp;gt; 2.3&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;2.2999999999999998&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; decimal.Decimal(&amp;quot; 1.1&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Decimal(&amp;quot;1.1&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; decimal.Decimal(&amp;quot; 2.3&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Decimal(&amp;quot;2.3&amp;quot;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;在算术中能保持准确性.以浮点数为例:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; 0.1 + 0.1 + 0.1 -  0.3&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;5.5511151231257827e-17&lt;/span&gt;&lt;br&gt;&lt;br&gt;上面的差值很接近于0,但它们不能通过等于测试,如:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; 0.1+0.1+0.1-0.3==0.0 &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;False&lt;/span&gt;&lt;br&gt;&lt;br&gt;而且这些偏差会积累下去,因此,在需要保持准确性的场合,应该使用decimal:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; d1 = decimal.Decimal(&amp;quot; 0.1&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; d3 = decimal.Decimal(&amp;quot;0.3&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; d1 + d1 + d1 - d3 &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Decimal(&amp;quot;0.0&amp;quot;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;decimal.Decimal实例可以从整数,字符串或者元组构造.要从浮点数构造decimal,首先应该把浮点数转换为字符串.Decimal数字包含很多特殊数字,比如NaN(表示非数字),正的和负的无穷大, 还有-0.一旦构造好后,decimal数字是不能修改的,和Python中别的数字一样.&lt;br&gt;decimal模块实现了一些学校里面教过的基本运算法则.为了保证精度,小数位数尽可能的给出最多.&lt;br&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; 0.9 / 10&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;0.089999999999999997&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; decimal.Decimal(&amp;quot;0.9&amp;quot;) / decimal.Decimal(10)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;Decimal(&amp;quot;0.09&amp;quot;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;当小数位数超过允许的精度后,它使用当前的保留方式来保留小数.有很多保留方式,默认的是round-half-even.&lt;br&gt;decimal模块采用保留位数0的方式,比如:1.30+1.20=2.50.这在一些金融应用程序中是有用的,对于乘法,也保留了位数0:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;gt;&amp;gt;&amp;gt; decimal.Decimal(&amp;quot;1.3&amp;quot;) * decimal.Decimal(&amp;quot;1.2&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Decimal(&amp;quot;1.56&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; decimal.Decimal(&amp;quot;1.30&amp;quot;) * decimal.Decimal(&amp;quot;1.20&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Decimal(&amp;quot;1.5600&amp;quot;) &lt;/span&gt;&lt;br&gt;&lt;br&gt;decimal除了有内建数字类型的通用方法外,它还有自己特有的方法,你可以自己查看帮助.&lt;br&gt;decimal依赖于上下文环境工作,也就是说,你可以设置它的工作方式(集合).每一个线程也有自己的上下文(也就是说,你可以改变一个线程,而不影响其它的);修改线程上下文的方式就是使用decimal模块的getcontext和setcontext函数.&lt;br&gt;和由机器决定精度的浮点数不同,decimal可以有用户设置精度(默认是28为),它可以被设置到需要的大小: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; decimal.getcontext( ).prec = 6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # set the precision to 6...&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; decimal.Decimal (1) / decimal.Decimal(7)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Decimal(&amp;quot;0.142857&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt;  decimal.getcontext( ).prec = 60&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # ...and to 60 digits&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;gt;&amp;gt;&amp;gt; decimal.Decimal(1) / decimal.Decimal(7)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;Decimal(&amp;quot;0.142857142857142857142857142857142857142857142857142857142857&amp;quot;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;当然,并不是所有的decimal函数都像前面举例的那样简单.基本上,decimal实现了十进制数标准,你可以参考&lt;span class="docLink"&gt;&lt;a href="http://www2.hursley.ibm.com/decimal/"&gt; http://www2.hursley.ibm.com/decimal/&lt;/a&gt;&lt;/span&gt;. 在实际中,decimal实现了信号,信号表示一些不寻常的计算结果(比如:1/0,0/0,无穷大/无穷大等).如果你的程序不需要信号,它可以被忽略或者做为信息,甚至异常.每一个信号,都有一个标志和陷阱.当信号出现的时候,标志加一,陷阱被设置为1,一个异常就抛出了.这给了程序员很大的方便来使用decimal.&lt;br&gt;既然decimal有这么多的好处,为什么还有人坚持使用float?的确,有什么原因让Python把float做为(也是唯一)非整数的数据类型?当然有很多原因可以列出来,但最关键的就是速度,比如: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;$ python -mtimeit -s&amp;#39;from decimal import Decimal as D&amp;#39; &amp;#39;D(&amp;quot;1.2&amp;quot;)+D(&amp;quot;3.4&amp;quot;)&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; 10000 loops, best of 3: 191 usec per loop&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;$ python -mtimeit -s&amp;#39;from decimal import Decimal as D&amp;#39; &amp;#39;1.2+3.4&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;1000000 loops, best of 3: 0.339 usec per loop&lt;/span&gt;&lt;br&gt;&lt;br&gt;简单的说:在这台计算机上(Athlon 1.2GHz,Linux),Python每秒能运行3百万次float加法,但是只能运行5000多次Decimal加法.&lt;br&gt;基本上,如果你的程序要计算成千上万的非整数,你最好坚持使用float!因为...(一系列原因),所以还是使用浮点数吧. &lt;br&gt;当然,并不是所有的程序都要进行大量的非整数运算,所以我们还是可以方便的使用decimal的.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; Batteries Included:&lt;/span&gt;&lt;br&gt;&lt;br&gt;Plone对Batteries Included&lt;span style="background-color: rgb(255, 255, 255);"&gt;的注解是：&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Supports Linux, Windows, Mac OS X, FreeBSD, Solaris. The installers get &lt;/span&gt;&lt;br style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;you up and running within minutes. No complex set-up procedures.&lt;/span&gt;&lt;br style="color: rgb(0, 0, 0);"&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;round-half-even &lt;/span&gt;&lt;br&gt;&lt;br&gt;如果舍弃部分左边的数字为奇数，则作 &amp;nbsp; ROUND_HALF_UP &amp;nbsp; ；如果它为偶数，则作 &amp;nbsp; ROUND_HALF_DOWN &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-5883573148277042522?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/5883573148277042522/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=5883573148277042522' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5883573148277042522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5883573148277042522'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-30-python.html' title='Python Cookbook 3.0 Python时间和货币概述'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4334491557838249126</id><published>2007-08-02T10:38:00.001+08:00</published><updated>2007-08-02T10:38:14.366+08:00</updated><title type='text'>Python Cookbook 2.30 计算CRC-64循环冗余校验</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;为了保证数据的正确性,你需要使用循环冗余校验(CRC)来检查数据,而且使用CRC-64算法,并满足ISO-3309标准.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;Python标准库没有实现CRC-64算法(只实现了CRC-32,在zlib.crc32),所以我们需要自己编写.幸运的是 ,Python的位运算和C一样简便,所以很融入将一个标准的算法转换为Python实现:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# prepare two auxiliary tables tables (using a function, for speed),&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; # then remove the function, since it&amp;#39;s not needed any more:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;CRCTableh = [0] * 256&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; CRCTablel = [0] * 256&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def _inittables(CRCTableh, CRCTablel, POLY64REVh, BIT_TOGGLE):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; for i in xrange(256):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; partl = i&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parth = 0L&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for j in xrange(8):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rflag = partl &amp;amp; 1L&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; partl &amp;gt;&amp;gt;= 1L&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if parth &amp;amp; 1:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; partl ^= BIT_TOGGLE&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parth &amp;gt;&amp;gt;= 1L&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if rflag:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parth ^= POLY64REVh&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CRCTableh[i] = parth &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CRCTablel[i] = partl&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# first 32 bits of generator polynomial for CRC64 (the 32 lower bits are &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# assumed to be zero) and bit-toggle mask used in _inittables&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;POLY64REVh = 0xd8000000L &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;BIT_TOGGLE = 1L &amp;lt;&amp;lt; 31L&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# run the function to prepare the tables &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;_inittables(CRCTableh, CRCTablel, POLY64REVh, BIT_TOGGLE)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# remove all names we don&amp;#39;t need any more, including the function &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;del _inittables, POLY64REVh, BIT_TOGGLE&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# this module exposes the following two functions: crc64, crc64digest &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def crc64(bytes, (crch, crcl)=(0,0)):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for byte in bytes:&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; shr = (crch &amp;amp; 0xFF) &amp;lt;&amp;lt; 24&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temp1h = crch &amp;gt;&amp;gt; 8L &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temp1l = (crcl &amp;gt;&amp;gt; 8L) | shr&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tableindex = (crcl ^ ord(byte)) &amp;amp; 0xFF &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; crch = temp1h ^ CRCTableh[tableindex]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; crcl = temp1l ^ CRCTablel[tableindex] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return crch, crcl&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def crc64digest(aString):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &amp;quot;%08X%08X&amp;quot; % (crc64(bytes))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # a little test/demo, for when this module runs as main-script&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert crc64(&amp;quot;IHATEMATH&amp;quot;) == (3822890454, 2600578513) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert crc64digest(&amp;quot;IHATEMATH&amp;quot;) == &amp;quot;E3DCADD69B01ADD1&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;crc64: dumb test successful&amp;#39;&lt;/span&gt;&lt;br&gt;&lt;br&gt;循环冗余校验是验证文件正确性的常用算法,CRC可以很好的检查到数据损坏,但它不像其它较强的算法那样提供预防数据损坏的机制.CRC比其它的校验算法更快,在只关心数据是否破坏的场景下,CRC非常适用.&lt;br&gt;从数学上讲,CRC对我们要检测的数据进行按位多项式计算.在实践中,如本节所示,大多数计算可以一次完成并加入表中,如果表中的数据被正确的索引的话.在初始化后 (我们使用大量局部变量,因为在Python中,局部变量计算要比全局变量快).事实上CRC计算是非常快的,表中的运算和CRC算法都需要大量的位运算,还好Python的位运算速度可以和C想匹敌(其实语法也很类似).&lt;br&gt;计算CRC-64的算法在ISO-3309标准中描述了,本节所做的只是实现这个算法罢了,生成多项式是x64 + x4 + x3 + x + 1.我们使用一对Python的int来表示结果,它们分别保存结果的高32位和低32位.为了让CRC能持续的计算 ,比如一次只计算一小段数据,我们在调用CRC64前先对它进行初始化(crch,crcl),其值为前面计算的结果.对于一次性计算CRC的场景来说,我们将数据以字符串的形式传入方法即可,其初始化化值为(0,0),也是方法的默认值.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;由于英语水平有限,本节内容不能做到信达雅了,不过一切尽在代码中.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4334491557838249126?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4334491557838249126/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4334491557838249126' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4334491557838249126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4334491557838249126'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-230-crc-64.html' title='Python Cookbook 2.30 计算CRC-64循环冗余校验'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-5276267814353052865</id><published>2007-08-01T10:19:00.001+08:00</published><updated>2007-08-01T10:19:38.063+08:00</updated><title type='text'>Python Cookbook 2.29 为文件名添加版本号</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要对文件进行备份,在备份的时候,想给文件名添加标准的3位数版本号.如.001.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;我们要写代码来实现这个功能:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def VersionFile(file_spec, vtype=&amp;#39;copy&amp;#39;): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import os, shutil&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if os.path.isfile(file_spec):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # check the &amp;#39;vtype&amp;#39; parameter&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if vtype not in (&amp;#39;copy&amp;#39;, &amp;#39;rename&amp;#39;):&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise ValueError, &amp;#39;Unknown vtype %r&amp;#39; % (vtype,)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Determine root filename so the extension doesn&amp;#39;t get longer &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; n, e = os.path.splitext(file_spec)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Is e a three-digits integer preceded by a dot? &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len(e) == 4 and e[1:].isdigit( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; num = 1 + int(e[1:]) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; root = n&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; num = 0&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; root = file_spec&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Find next available file version&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in xrange(num, 1000):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new_file = &amp;#39;%s.%03d&amp;#39; % (root, i)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not os.path.exists(new_file):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if vtype == &amp;#39;copy&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; shutil.copy(file_spec, new_file)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; os.rename(file_spec, new_file)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return True&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise RuntimeError, &amp;quot;Can&amp;#39;t %s %r, all names taken&amp;quot;%(vtype,file_spec)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return False&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; import os&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # create a dummy file &amp;#39;test.txt&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tfn = &amp;#39; test.txt&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open(tfn, &amp;#39;w&amp;#39;).close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # version it 3 times &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print VersionFile(tfn)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # emits: True&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print VersionFile(tfn)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # emits: True&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print VersionFile(tfn)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # emits: True&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # remove all  test.txt* files we just made&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for x in (&amp;#39;&amp;#39;, &amp;#39;.000&amp;#39;, &amp;#39;.001&amp;#39;, &amp;#39;.002&amp;#39;):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; os.unlink(tfn + x)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # show what happens when the file does not exist&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print VersionFile(tfn)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # emits: False&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print VersionFile(tfn)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # emits: False&lt;/span&gt;&lt;br&gt;&lt;br&gt;上面代码的目的是在你更新文件内容之前,确保它已经被复制或者重命名(由参数决定),在你修改文件之间,备份它们是一个比较好的习惯.最终进行复制和重命名操作的是shutil.copy和os.rename ,所以问题的核心就是要找到需要操作的文件名.&lt;br&gt;判断备份文件的一种流行的方式就是版本号,本节获取新文件名的方法是首先获得它的原始文件名(如果文件以前有版本号的话),然后为文件添加版本号,如.000,.001,直到没有重复的文件名存在为止.此时,使用文件重命名方法来修改文件名.需要注意的是VersionFile函数只能判断1000个版本号,在你使用它之前需要明白这一点.在文件备份之前,它必须存在,否则你无法操作(MS废话),当然,如果文件不存在,VersionFile会返回False(当成功执行改名后返回True;),所以你也不用在使用它前来写代码判断文件是否存在. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;os.&lt;/span&gt;rename(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rename(old, new)&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Rename a file or directory.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt; shutil.&lt;/span&gt;copy(src, dst)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Copy data and mode bits (&amp;quot;cp src dst&amp;quot;).&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The destination may be a directory.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-5276267814353052865?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/5276267814353052865/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=5276267814353052865' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5276267814353052865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5276267814353052865'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-229.html' title='Python Cookbook 2.29 为文件名添加版本号'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-3320604364334144706</id><published>2007-08-01T10:00:00.001+08:00</published><updated>2007-08-01T10:00:36.720+08:00</updated><title type='text'>Python Cookbook 2.28 使用跨平台API锁定文件</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要在一个程序中锁定文件,而此程序又可以同时运行在Windows和类Uiux系统上,但是Python标准库并没有提供通用的函数来实现这个功能,只有特定平台的库提供相关函数.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;当Python标准库没有提供跨平台解决方案的时候,通常需要我们自己写一个: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import os&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# needs win32all to work on Windows (NT, 2K, XP, _not_ /95 or /98)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;if &lt;a href="http://os.name"&gt;os.name&lt;/a&gt; == &amp;#39;nt&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import win32con, win32file, pywintypes&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LOCK_SH = 0 # the default &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _ _overlapped =  pywintypes.OVERLAPPED( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def lock(file, flags):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hfile = win32file._get_osfhandle( file.fileno( ))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; win32file.LockFileEx(hfile, flags, 0, 0xffff0000, _ _overlapped)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; def unlock(file):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hfile = win32file._get_osfhandle(file.fileno( ))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; win32file.UnlockFileEx(hfile, 0, 0xffff0000, _ _overlapped)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;elif &lt;a href="http://os.name"&gt;os.name&lt;/a&gt; == &amp;#39;posix&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; from fcntl import LOCK_EX, LOCK_SH, LOCK_NB&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def lock(file, flags):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fcntl.flock(file.fileno( ), flags)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def unlock(file):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fcntl.flock(file.fileno( ), fcntl.LOCK_UN)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; raise RuntimeError(&amp;quot;PortaLocker only defined for nt and posix platforms&amp;quot;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;当多个程序或线程访问共享文件时,需要保证操作是同步的,否则两个进程可能同时去修改一个文件.同步操作的失败有可能导致文件的损害.&lt;br&gt;本节提供了两个函数:lock和unlock,分别用于给文件加锁和解锁.使用portalock.py模块很简单 ,只要调用lock方法,并将文件名和锁类型做为参数就可以了:&lt;br&gt;&lt;br&gt;共享锁(Shared Lock,默认)&lt;br&gt;这种锁拒绝所有进程的写操作,包括加锁的进程.所有的进程都可以进行读操作.&lt;br&gt;&lt;br&gt;排它锁(Exclusive Lock)&lt;br&gt;这种锁拒绝别的进程读或者写文件.&lt;br&gt;&lt;br&gt;非阻塞锁(Nonblocking Lock)&lt;br&gt;当该值被设定时,函数如果发现不能应用要求加的锁,就立刻返回,否则就等待.LOCK_NB 可以进行或操作,可以是LOCK_SH或LOCK_EX.&lt;br&gt;&lt;br&gt;举例说明:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import portalocker&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;afile = open(&amp;quot;somefile&amp;quot;, &amp;quot;r+&amp;quot;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;portalocker.lock(afile, portalocker.LOCK_EX)&lt;/span&gt;&lt;br&gt;&lt;br&gt;不同的操作系统对文件锁的实现是完全不同的.在类Unix系统上(包括Linux 和Mac OS),上面的代码依赖fcntl库中的函数,而在Windows平台上(2000,NT,XP),它使用win32file模块, 是PyWin32扩展的一部分.但是重点是,不考虑平台无关性,代码中访问系统的方式和你传递的参数(flags)都是一样的.这些跨平台包虽然实现不同,可是却能方便利用于写跨平台程序,这也是Python的优点之一.&lt;br&gt;当你写跨平台程序时,比较好的方式是封装你的操作.就文件加锁来说,对于那些需要使用跨平台lock操作的用户,是非常有用的.更一般的情况,if os.name==这样的语句不应该是应用程序级别的代码,它应该处于标准库或者独立于应用程序的模块中,如本节的代码. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;本节所演示的代码就是portalocker.py &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-3320604364334144706?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/3320604364334144706/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=3320604364334144706' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3320604364334144706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3320604364334144706'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/08/python-cookbook-228-api.html' title='Python Cookbook 2.28 使用跨平台API锁定文件'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-7490271477919016262</id><published>2007-07-31T17:42:00.001+08:00</published><updated>2007-07-31T17:42:27.108+08:00</updated><title type='text'>Python Cookbook 2.27 从Microsoft Word文档中获取文本</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要将目录树中的Microsoft Word文档的内容提取出来,并保存到对应的文本文档中.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;使用PyWin32扩展,我们可以使用COM来访问Word,这样能实现需求:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import fnmatch, os, sys, win32com.client&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;wordapp = win32com.client.gencache.EnsureDispatch(&amp;quot;Word.Application&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;try:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for path, dirs, files in os.walk(sys.argv[1]):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for filename in files:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not fnmatch.fnmatch(filename, &amp;#39;*.doc&amp;#39;): continue&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; doc = os.path.abspath(os.path.join(path, filename))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;processing %s&amp;quot; % doc &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wordapp.Documents.Open(doc)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; docastxt = doc[:-3] + &amp;#39;txt&amp;#39; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wordapp.ActiveDocument.SaveAs(docastxt,&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileFormat= win32com.client.constants.wdFormatText)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wordapp.ActiveDocument.Close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; finally:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # ensure Word is properly shut down even if we get an exception&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; wordapp.Quit( )&lt;/span&gt;&lt;br&gt;&lt;br&gt;对于Windows应用程序来说,有一个很好的特点是脚本可以使用COM来访问它们.而PyWin32扩展使得用Python使用COM变得异常容易.这个扩展能让你通过脚本完成许多windows系统任务,本节的脚本驱动Microsoft Word将目录树下的.doc文档中取出文本并存到对应的txt文档中.使用os.walk函数,我们可以简单的用一个for循环来遍历目录树,使用fnmatch.fnmatch函数 ,我们可以判断一个文件是否满足指定的扩展名,这里是&amp;#39;.doc&amp;#39;,一旦我们确定文件是word文件,我们使用os.path来获得它的绝对路径,然后使用Word打开它,并保存文本内容为txt.&lt;br&gt;如果你没有安装Word,你需要使用完全不同的方法,一个方案是使用Open Office,它可以加载Word文档.另外的方法就是使用别的程序来读Word文档,如AntiWord等.我们在这里不做讨论了.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-7490271477919016262?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/7490271477919016262/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=7490271477919016262' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7490271477919016262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7490271477919016262'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-227-microsoft-word.html' title='Python Cookbook 2.27 从Microsoft Word文档中获取文本'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-279927062597630947</id><published>2007-07-30T11:08:00.001+08:00</published><updated>2007-07-30T11:08:51.855+08:00</updated><title type='text'>Python Cookbook 2.26 从OpenOffice文档中获取文本</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要从OpenOffice文档中获取文本内容(保留或者不保留XML标记).&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;OpenOffice是由用一系列定义好的XML文档压缩(zip)而成.要获取文档的原始信息,我们甚至可以不用安装OpenOffice:&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;import zipfile, re&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;rx_stripxml = re.compile(&amp;quot;&amp;lt;[^&amp;gt;]*?&amp;gt;&amp;quot;, re.DOTALL|re.MULTILINE)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;def convert_OO(filename, want_text=True):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Convert an OpenOffice.org document to XML or text. &amp;quot;&amp;quot;&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; zf = zipfile.ZipFile(filename, &amp;quot;r&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data =  zf.read(&amp;quot;content.xml&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; zf.close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if want_text: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data = &amp;quot; &amp;quot;.join(rx_stripxml.sub(&amp;quot; &amp;quot;, data).split( ))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return data&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _==&amp;quot;_ _main_ _&amp;quot;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import sys &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len(sys.argv)&amp;gt;1:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for docname in sys.argv[1:]:&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Text of&amp;#39;, docname, &amp;#39;:&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print convert_OO(docname) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;XML of&amp;#39;, docname, &amp;#39;:&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print convert_OO(docname, want_text=False) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Call with paths to OO.o doc files to see Text and XML forms.&amp;#39; &lt;/span&gt;&lt;br&gt;&lt;br&gt;OpenOffice文档实际上是zip文档,除了别的内容外,其中会包含content.xml,本节的目的就是要获取这个文档的信息.默认情况下,本节的代码使用简单的正则式去掉了xml标记.当然,我们可以使用一个xml解析器来获得更多的信息,可是如果只需要文本内容的话,使用最直接的方法就可以了.&lt;br&gt;正则式rx_stripxml 会匹配所有的xml标记,从&amp;quot;&amp;lt;&amp;quot;开始到&amp;quot;&amp;gt;&amp;quot; 结束.在函数Convert_OO中,在if want_text后面,我们将xml标记都替换成空格,然后使用split将它拆分,最后使用&amp;quot;&amp;quot;.join将其合并.基本上,使用分割-处理-合并方式将一系列空格转换为一个空字符,更多使用xml文件的方法将在12.3节中给出.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-279927062597630947?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/279927062597630947/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=279927062597630947' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/279927062597630947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/279927062597630947'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-226-openoffice.html' title='Python Cookbook 2.26 从OpenOffice文档中获取文本'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-310152860862704607</id><published>2007-07-30T10:43:00.001+08:00</published><updated>2007-07-30T10:43:52.612+08:00</updated><title type='text'>Python Cookbook 2.25 在Windows系统上改变文件属性</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要在windows系统下设置文件的属性,比如要将文件属性设置为只读,归档等.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;PyWin32&amp;#39;s的win32api模块提供了方法SetFileAttributes,使得这个问题的解决方案变得异常简单: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import win32con, win32api, os&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# create a file, just to show how to manipulate it&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;thefile = &amp;#39;test&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;f = open(&amp;#39;test&amp;#39;, &amp;#39;w&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; f.close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# to make the file hidden...:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;win32api.SetFileAttributes (thefile, win32con.FILE_ATTRIBUTE_HIDDEN)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# to make the file readonly:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; win32api.SetFileAttributes(thefile, win32con.FILE_ATTRIBUTE_READONLY)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# to be able to delete the file we need to set it back to normal:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;win32api.SetFileAttributes(thefile, win32con.FILE_ATTRIBUTE_NORMAL)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# and finally we remove the file we just made &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;os.remove(thefile)&lt;/span&gt;&lt;br&gt;&lt;br&gt;使用win32api.SetFileAttributes的一个好处是可以增强删除文件功能.使用os.remove方法在windows平台上可能会失败,如果文件属性不是默认的情况下.我们可以先使用SetFileAttributes将它设置为默认属性 ,然后删除之.不过需要注意的是,你要清楚的知道自己删除的是什么文件.不要造成不必要的损失.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;win32api的文档在:&lt;br&gt; &lt;p class="docText"&gt;&lt;a class="docLink" href="http://aspn.activestate.com/ASPN/Python/Reference/Products/ActivePython/PythonWin32Extensions/win32file.html" target="_blank"&gt;http://ASPN.ActiveState.com/ASPN/Python/Reference/Products/ActivePython/PythonWin32Extensions/win32file.html &lt;/a&gt;&lt;/p&gt; &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-310152860862704607?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/310152860862704607/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=310152860862704607' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/310152860862704607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/310152860862704607'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-225-windows.html' title='Python Cookbook 2.25 在Windows系统上改变文件属性'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-6387196503094792616</id><published>2007-07-30T10:33:00.001+08:00</published><updated>2007-07-30T10:33:13.502+08:00</updated><title type='text'>Python Cookbook 2.24 在Mac OS系统上统计PDF文档的页数</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;假如你的系统是Mac OS(10.3或以后),你希望统计一个PDF文档的页数.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;PDF格式和Python都是Mac OS默认支持的,实现本节的需求异常简单:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; #!/usr/bin python&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import CoreGraphics&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def pageCount(pdfPath):&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Return the number of pages for the PDF document at the given path.&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; pdf = CoreGraphics.CGPDFDocumentCreateWithProvider(&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CoreGraphics.CGDataProviderCreateWithFilename(pdfPath)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return pdf.getNumberOfPages( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import sys&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for path in  sys.argv[1:]:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print pageCount(path)&lt;/span&gt;&lt;br&gt;&lt;br&gt;另一个解决方法是使用Python的PyObjC扩展,这样能使代码在Mac OS的Foundation和AppKit框架下都能工作,这样你的脚本在比较旧的Mac&amp;nbsp; OS版本上也能使用了, 比如10.2 Jaguar.在10.3以后的Mac OS版本中,请确保Python安装在你的系统下,你才能使用一些比较有用的Python模块,比如CoreGraphics,这样你才能用一些Apple&amp;#39;s的Quartz图形引擎.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;我没有见过Mac OS,本节的内容基本不明白,立此存照吧.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-6387196503094792616?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/6387196503094792616/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=6387196503094792616' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6387196503094792616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6387196503094792616'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-224-mac-ospdf.html' title='Python Cookbook 2.24 在Mac OS系统上统计PDF文档的页数'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-6184059693753086743</id><published>2007-07-27T11:40:00.001+08:00</published><updated>2007-07-27T11:40:10.824+08:00</updated><title type='text'>Python Cookbook 2.23 从控制台读不回显字符--跨平台方式</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你的程序需要从控制台读入字符,一次一个,不显示在屏幕上,而且要跨平台.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;当面对跨平台问题时,我们需要封装代码,让他们看起来都是一样的:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; try:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; from msvcrt import getch&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;except ImportError:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39; we&amp;#39;re not on Windows, so we try the Unix-like approach &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def getch( ): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; import sys, tty, termios&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fd = sys.stdin.fileno( ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; old_settings = termios.tcgetattr(fd)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tty.setraw(fd)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ch = sys.stdin.read(1)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ch&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;在windows平台上,Python标准库msvcrt提供了一个很方便的方法getch,来一次一个从键盘读字符,且不回显.然而,这个模块不是类Unix平台上的标准模块之一,我们可以使用tty和termios模块来实现这个功能(当然,这两个模块也不是windows版本Python的标准模块). &lt;br&gt;在应用程序的角度,我们不应该考虑这些问题,而且,我们应该用跨平台的思路来写程序,而不是去记忆不同平台的标准库有什么区别.Python解决了大部分跨平台的问题,但不是全部.本节的例子就是就是它没有解决的跨平台问题之一.&lt;br&gt;当我们不能找到一个现成的跨平台的包时,我们应该自己封装一个来使用.本节的代码不仅说明了如何解决问题,也提供了一个编写Python的包的好的方式,&lt;br&gt;你自己写的模块中,如果要使用与平台相关的标准库时,要用try语句将import包起来,并处理好expect  ImportError异常.在expect块的代码中,你可以自己处理如何在另一个平台运行的代码.对于罕见的情况,有时不只需要判断两个平台.但大多数情况下,所有非windows平台都可以属于类unix平台.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-6184059693753086743?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/6184059693753086743/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=6184059693753086743' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6184059693753086743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6184059693753086743'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-223.html' title='Python Cookbook 2.23 从控制台读不回显字符--跨平台方式'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-3047063263551826670</id><published>2007-07-27T09:34:00.001+08:00</published><updated>2007-07-27T09:34:11.602+08:00</updated><title type='text'>算法学习:楼梯问题</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;有一个台阶数为N的楼梯,可以有两种等楼梯的方法:一次上一阶,或者一次上两阶.问对于N阶楼梯,共有多少种不同的上法?&lt;br&gt;如:&lt;br&gt;N=1:&amp;nbsp; 1种&lt;br&gt;N=3:&amp;nbsp; 3种(1+1+1, 1+2, 2+1)&lt;br&gt;N=4:&amp;nbsp; 5种(1+1+1+1, 1+2+1, 1+1+2, ,2+1+1, 2+2)&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; 算法:&lt;/span&gt;&lt;br&gt;&lt;br&gt;1.这个题目咋一看似乎是数的拆分问题的一种,可以用解决拆分问题的方法来解决.&lt;br&gt;&lt;br&gt;2.比较简单的方法是递推求解:&lt;br&gt;设Y为台阶数为N时,上楼梯的方法数.则:&lt;br&gt;N=1, Y=1&lt;br&gt;N=2, Y=2&lt;br&gt;N=3, Y=3&lt;br&gt;N=4, Y=5&lt;br&gt;N=5, Y=8&lt;br&gt;......&lt;br&gt;如果仔细观察Y值,可以发现满足Fibonacci数列.可是我不会证明,记得以前我们高中老师证明过一次,可是当时就没有看懂. &lt;br&gt;如果这样,解法就相当简单了.&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def Stairways(N):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a,b=0,1&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; for i in xrange(n):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a,b=b,a+b&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return b&lt;/span&gt;&lt;br&gt; &lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果题目要求打印出所有的方法步骤,还是使用拆分发比较好.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-3047063263551826670?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/3047063263551826670/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=3047063263551826670' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3047063263551826670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3047063263551826670'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/blog-post_27.html' title='算法学习:楼梯问题'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-7763192387108355999</id><published>2007-07-26T17:23:00.001+08:00</published><updated>2007-07-26T17:23:52.125+08:00</updated><title type='text'>Python Cookbook 2.22 在两个路径间计算相对路径</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要知道从一个目录到另一个目录的相对路径,比如,想创建 一个符号连接或者在URL中引用.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;最简单的办法就是将路径分割成目录列表,然后依次处理.我们可以写一个助手方法来实现:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import os, itertools&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def all_equal(elements):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39; return True if all the elements are equal, otherwise False. &amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; first_element = elements[0]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for other_element in elements[1:]: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if other_element != first_element: return False&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return True &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def common_prefix(*sequences):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39; return a list of common elements at the start of all sequences, &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; then a list of lists that are the unique tails of each sequence. &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; # if there are no sequences at all, we&amp;#39;re done&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not sequences: return [&amp;nbsp; ], [&amp;nbsp; ]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; # loop in parallel on the sequences &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; common = [&amp;nbsp; ]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for elements in itertools.izip(*sequences): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # unless all elements are equal, bail out of the loop&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not all_equal(elements): break &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # got one more common element, append it and keep looping &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; common.append(elements[0])&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # return the common prefix and unique tails &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return common, [ sequence[len(common):] for sequence in sequences ]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; def relpath(p1, p2, sep=os.path.sep, pardir=os.path.pardir ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39; return a relative path from p1 equivalent to path p2.&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; In particular: the empty string, if p1 == p2;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p2, if p1 and p2 have no common prefix.&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; common, (u1, u2) = common_prefix(p1.split(sep), p2.split(sep))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; if not common:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return p2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # leave path absolute if nothing at all in common&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; return sep.join( [pardir]*len(u1) + u2 )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def test(p1, p2, sep= os.path.sep):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39; call function relpath and display arguments and results. &amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;from&amp;quot;, p1, &amp;quot;to&amp;quot;, p2, &amp;quot; -&amp;gt; &amp;quot;, relpath(p1, p2, sep)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test(&amp;#39;/a/b/c/d&amp;#39;, &amp;#39;/a/b/c1/d1&amp;#39;, &amp;#39;/&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; test(&amp;#39;/a/b/c/d&amp;#39;, &amp;#39;/a/b/c/d&amp;#39;, &amp;#39;/&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test(&amp;#39;c:/x/y/z&amp;#39;, &amp;#39;d:/x/y/z&amp;#39;, &amp;#39;/&amp;#39;)&lt;/span&gt;&lt;br&gt;&lt;br&gt;在本节的代码中,使用最多的是简单却又最常使用的common_prefix函数,给定该函数一个长度为N的序列,它返回序列中元素的共同前缀, 并分别返回由不同部分组成的列表.为了计算两个路径间的相对路径,我们可以忽略它们中相同的部分.我们只关心向上的层数就可以了(一般来说,用os.path,pardir表示,在Unix系统中用../来表示,我们需要用它来表示从开始路径向下的层数),然后添加不同的后缀就可以了.所以,函数relpath将路径分割成目录,然后调用common_prefix,接着计算共同的层数.&lt;br&gt;common_prefix代码中间的循环语句for elements in  itertools.izip(*sequences),因为izip语句只有当它遇到最短的元素的结尾时才会中止,所以我们的程序中需要自己判断获得的字串是不是在所有元素中都存在,并且将所有的公共元素都添加到common中,当循环结束的时候,我们通过common来对各个元素进行切片处理,以获得不同部分的列表.&lt;br&gt;函数all_euqal可以用另外一种简单的方式来实现,也是很有趣的:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; def all_equal(elements):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return len(dict.fromkeys(elements)) == 1&lt;/span&gt;&lt;br&gt;&lt;br&gt;或者,用更简单的方法,在Python2.4后有效:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; def all_equal(elements):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return len(set(elements)) == 1&lt;/span&gt;&lt;br&gt;&lt;br&gt;因为所有元素相等等价于所有元素组成的集合的大小为1,是使用dict.fromkeys的版本中,我们使用dict来模拟set的功能,所以它可以在Python2.3和2.4中工作 ,而set版本只能在2.4中工作.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;class izip(__builtin__.object)&lt;/span&gt;&lt;br&gt;&amp;nbsp;|&amp;nbsp; izip(iter1 [,iter2 [...]]) --&amp;gt; izip object&lt;br&gt;&amp;nbsp;|&lt;br&gt;&amp;nbsp;|&amp;nbsp; Return a izip object whose .next() method returns a tuple where &lt;br&gt;&amp;nbsp;|&amp;nbsp; the i-th element comes from the i-th iterable argument.&amp;nbsp; The .next()&lt;br&gt;&amp;nbsp;|&amp;nbsp; method continues until the shortest iterable in the argument sequence&lt;br&gt;&amp;nbsp;|&amp;nbsp; is exhausted and then it raises StopIteration.&amp;nbsp; Works like the zip() &lt;br&gt;&amp;nbsp;|&amp;nbsp; function but consumes less memory by returning an iterator instead of&lt;br&gt;&amp;nbsp;|&amp;nbsp; a list.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-7763192387108355999?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/7763192387108355999/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=7763192387108355999' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7763192387108355999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7763192387108355999'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-222.html' title='Python Cookbook 2.22 在两个路径间计算相对路径'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4782401483633245607</id><published>2007-07-25T16:58:00.001+08:00</published><updated>2007-07-25T16:58:48.998+08:00</updated><title type='text'>Python Cookbook 2.21 动态修改Python搜索路径</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;只有当模块在Python的搜索路径中时,它们才能被引用.可是如果因此而设置巨大的搜索路径,很影响效率.因为我们需要动态调整搜索路径.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;我们只要简单的给sys.path添加目录就可以了,需要注意的是避免重复字段:&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;def AddSysPath(new_path):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; AddSysPath(new_path): adds a &amp;quot;directory&amp;quot; to Python&amp;#39;s  sys.path&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Does not add the directory if it does not exist or if it&amp;#39;s already on&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; sys.path. Returns 1 if OK, -1 if new_path does not exist, 0 if it was&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; already on sys.path.&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; import sys, os&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Avoid adding nonexistent paths&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not  os.path.exists(new_path): return -1&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Standardize the path.&amp;nbsp; Windows is case-insensitive, so lowercase&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # for definiteness if we are on Windows. &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new_path = os.path.abspath(new_path)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if sys.platform == &amp;#39;win32&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new_path = new_path.lower( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Check against all currently available paths &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for x in sys.path:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x =  os.path.abspath(x)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if sys.platform == &amp;#39;win32&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x =  x.lower( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if new_path in (x, x + os.sep):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0 &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sys.path.append(new_path)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # if you want the new_path to take precedence over existing &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # directories already in sys.path, instead of appending, use:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; # sys.path.insert(0, new_path)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 1&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Test and show usage&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import sys&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Before:&amp;#39; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for x in sys.path: print x&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if sys.platform == &amp;#39;win32&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print AddSysPath(&amp;#39;c:\\Temp&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print AddSysPath(&amp;#39;c:\\temp&amp;#39;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print AddSysPath(&amp;#39;/usr/lib/my&lt;/span&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; _modules&amp;#39;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;After:&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for x in sys.path: print x&lt;/span&gt; &lt;br&gt;&lt;br&gt;模块在被引用前,必须存在于Python的搜索路径中,而我们不能因此就给Python搜索路径添加巨多的项目,这样会影响别的Python应用程序的执行效率.本节采用的方法是动态给sys.path添加目录,而且这个目录必须是存在且sys.path中没有的.&lt;br&gt;sys.path是一个列表,所以很容易通过sys.path.append向它的后面添加元素,添加完毕后,Python会在新的搜索路径中依次搜索目录,这就是说,你可以使用sys.path.insert (0..),这样保证Python总是先搜索我们添加的目录.&lt;br&gt;如果给sys.path中添加重复目录或者无效的目录都没有问题,因为Python的import很聪明,能自动去除这些项.每次这样的问题发生的时候(如,遇到无效目录,或者重复目录,要处理系统报出的错误),都要花掉一点时间来处理.为了节约这些时间,本节给出的方法是避免给sys.path添加无效的或者重复的目录.这些添加的目录,只有在程序运行时有效,不会影响别的程序.&lt;br&gt;&lt;br&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4782401483633245607?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4782401483633245607/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4782401483633245607' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4782401483633245607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4782401483633245607'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-221-python.html' title='Python Cookbook 2.21 动态修改Python搜索路径'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-8033336701564757680</id><published>2007-07-25T10:19:00.001+08:00</published><updated>2007-07-25T10:19:47.870+08:00</updated><title type='text'>Python Cookbook 2.20 在Python搜索路径中查找文件</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;一个很大的Python应用,引用了很多资源文件(比如:项目文件,SQL脚本,图片等),你希望将它们放到一起,以便打包.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;需要在Python搜索路径中查找,该路径保存在sys.path中:&lt;br&gt;&lt;br&gt;import sys, os &lt;br&gt;class Error(Exception): pass&lt;br&gt;def _find(pathname, matchFunc=os.path.isfile):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for dirname in sys.path:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; candidate = os.path.join(dirname, pathname)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if matchFunc(candidate):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return candidate &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise Error(&amp;quot;Can&amp;#39;t find file %s&amp;quot; % pathname)&lt;br&gt;def findFile(pathname):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _find(pathname)&lt;br&gt;def findDir(path):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _find(path, matchFunc=os.path.isdir)&lt;br&gt;&lt;br&gt;大的Python应用由Python代码文件和很多资源文件组成.将它们放在一起对以后的使用和发布都是极为便利的 ,使用本节的方法或者2.18节的方法都很容易能找到它们.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;isdir(path)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Test whether a path is a directory&lt;br&gt;&lt;span style="font-weight: bold;"&gt; isfile(path)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Test whether a path is a regular file&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-8033336701564757680?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/8033336701564757680/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=8033336701564757680' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8033336701564757680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8033336701564757680'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-220-python.html' title='Python Cookbook 2.20 在Python搜索路径中查找文件'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-5438596330647861426</id><published>2007-07-24T18:00:00.001+08:00</published><updated>2007-07-24T18:00:47.066+08:00</updated><title type='text'>算法学习:排序</title><content type='html'>需求:&lt;br&gt;&lt;br&gt;讨论一些常见算法的实现.&lt;br&gt;&lt;br&gt;讨论:&lt;br&gt;&lt;br&gt;1.插入排序&lt;br&gt;&lt;br&gt;原理:找到适合的位置i,然后将i之后的元素后移,将元素放在i位置&lt;br&gt;&lt;br&gt;def InsertSort(array):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; n=len(array)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for j in xrange(1,n):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; key=array[j]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i=j-1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while i&amp;gt;=0 and array[i]&amp;gt;key: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[i+1]=array[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i-=1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[i+1]=key&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return array&lt;br&gt;if __name__ == &amp;#39;__main__&amp;#39;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print InsertSort([5,4,7,8,9,3,6,1,2,0])&lt;br&gt;&lt;br&gt;2.归并排序&lt;br&gt;&lt;br&gt;原理:首先将元素递归分组,确保每一组的元素是排序好的,然后将这些组合并即可. &lt;br&gt;&lt;br&gt;def MergeSort(array,left,right):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if left &amp;lt; right:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; middle = (left + right) &amp;gt;&amp;gt; 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MergeSort(array,left,middle)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MergeSort(array,middle+1,right)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Merge(array,left,middle,right) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return array&lt;br&gt;def Merge(array,left,middle,right):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; L=array[left:middle+1]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; L+=[65535]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; R=array[middle+1:right+1]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; R+=[65535]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i=j=0&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for k in xrange(left,right+1):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if L[i]&amp;lt;=R[j]:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[k]=L[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i+=1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[k]=R[j]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; j+=1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; except:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;i=%d,j=%d&amp;#39;%(i,j) &lt;br&gt;if __name__ == &amp;#39;__main__&amp;#39;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print MergeSort([5,4,7,8,9,3,6,1,2,0],0,9)&lt;br&gt;&lt;br&gt;其中加入两个边界值,当到边界值时,表示一组已经复制完毕.&lt;br&gt;&lt;br&gt;3.堆排序&lt;br&gt;&lt;br&gt;原理:建立最大堆,然后将root(最大)元素和堆的最后一个元素互换(最小)即可.然后减少堆的大小,循环执行.&lt;br&gt;&lt;br&gt;heapSize = 0&lt;br&gt; def MaxHeapify(array,i):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; global heapSize&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; l=(i+1 &amp;lt;&amp;lt; 1) - 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r=(i+1) &amp;lt;&amp;lt; 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; largest=0&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if l&amp;lt;heapSize and array[l] &amp;gt; array[i]:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; largest = l&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; largest = i &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if r&amp;lt;heapSize and array[r] &amp;gt; array[largest]:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; largest = r&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if largest != i:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = array[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[i] = array[largest]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[largest] = tmp&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MaxHeapify(array,largest) &lt;br&gt;&lt;br&gt;def BuildMaxHeap(array):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; global heapSize&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; heapSize= len(array)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in xrange(heapSize&amp;gt;&amp;gt;1,-1,-1):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MaxHeapify(array,i)&lt;br&gt;&lt;br&gt;def HeapSort(array):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; global heapSize&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BuildMaxHeap(array) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in xrange(len(array)-1,0,-1):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = array[0]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[0] = array[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[i] = tmp&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heapSize-=1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MaxHeapify(array,0)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return array&lt;br&gt;if __name__ == &amp;#39;__main__&amp;#39;: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print HeapSort([5,4,7,8,9,3,6,1,2,0])&lt;br&gt;&lt;br&gt;4.快速排序&lt;br&gt;&lt;br&gt;原理:利用分执法的优点,进行交换排序.在元素多的情况下,快速排序的表现最好.&lt;br&gt;&lt;br&gt;def QuickSort(array,left,right):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if left &amp;lt; right:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; middle = Partition(array,left,right)&lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QuickSort(array,left,middle-1)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QuickSort(array,middle+1,right)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return array&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;def Partition(array,left,right):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; x = array[right]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i = left - 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for j in xrange(left,right): &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if array[j] &amp;lt;= x:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i+=1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = array[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[i] = array[j]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[j] = tmp&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i+=1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = array[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[i] = array[right]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[right] = tmp &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return i&lt;br&gt;if __name__ == &amp;#39;__main__&amp;#39;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print QuickSort([5,4,7,8,9,3,6,1,2,0],0,9)&lt;br&gt;&lt;br&gt;5.给出一个生成随机序列的方法,我就是用这个方法测试的.&lt;br&gt;&lt;br&gt;def ArrayGenerator(n):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; array = range(0,n)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; from random import randint &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in xrange(0,n):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p = randint(i,n-1)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmp = array[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[i] = array[p]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array[p] = tmp&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return array&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-5438596330647861426?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/5438596330647861426/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=5438596330647861426' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5438596330647861426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/5438596330647861426'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/blog-post_24.html' title='算法学习:排序'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-388075394518323710</id><published>2007-07-23T12:00:00.001+08:00</published><updated>2007-07-23T12:00:50.278+08:00</updated><title type='text'>算法学习:求组合数</title><content type='html'>需求:&lt;br&gt;&lt;br&gt;给定一个数N,求出由序列[1..N]取出M个数的方法.&lt;br&gt;&lt;br&gt;讨论:&lt;br&gt;&lt;br&gt;求组合数有很多中算法,我认为最方便的就是二进制算法,算法的原理依据二项式定理,N的全组合数目为2^n-1.我们可以使用这个数的二进制形式来获得N的全组合.&lt;br&gt;&lt;br&gt;Python实现:&lt;br&gt;&lt;br&gt;def main(n,m=0):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; max = 2**n-1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def makeResult(num): &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i=1;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret=[]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while num &amp;gt; 0:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if num &amp;amp; 1:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.append(i)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; num&amp;gt;&amp;gt;=1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i+=1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while max &amp;gt; 0: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out=makeResult(max)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if m!=0:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len(out)==m:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print out&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print out&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; max-=1&lt;br&gt;if __name__ == &amp;#39;__main__&amp;#39;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; main(5,3) &lt;br&gt;&lt;br&gt;其中,max为2^n-1,我们让它递减至0,然后获得二进制中为1的位,并输出该位的位置,即获得的组合数.main的第二个参数是标志位,如果是0,求出全组合,如果不是0,取出特定个数的组合. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-388075394518323710?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/388075394518323710/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=388075394518323710' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/388075394518323710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/388075394518323710'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/blog-post_23.html' title='算法学习:求组合数'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-474646423201847355</id><published>2007-07-23T10:45:00.001+08:00</published><updated>2007-07-23T10:45:48.716+08:00</updated><title type='text'>Python Cookbook 2.19 在给定的路径中查找特定模式的文件</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;给定一个搜索路径(用分隔符分割的目录列表),需要找出目录下符合特定模式的所有文件.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;基本上,需要遍历搜索路径中所有的目录,循环方法可以封装在一个生成器中:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import glob, os&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def all_files(pattern, search_path, pathsep=os.pathsep):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Given a search path, yield all files matching the pattern. &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for path in search_path.split(pathsep): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for match in glob.glob(os.path.join(path, pattern)):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield match &lt;/span&gt;&lt;br&gt;&lt;br&gt;使用生成器有一个好处,你可以获得返回的第一个值,或者全部,以及其中的任何一个.比如,打印在你的PATH中满足&amp;#39;*.pye&amp;#39;的第一个文件名:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print all_files(&amp;#39;*.pye&amp;#39;, os.environ[&amp;#39;PATH&amp;#39;]).next( )&lt;/span&gt;&lt;br&gt;&lt;br&gt;要打印全部的,而且每行一个: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for match in all_files(&amp;#39;*.pye&amp;#39;, os.environ[&amp;#39;PATH&amp;#39;]):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print match&lt;/span&gt;&lt;br&gt;&lt;br&gt; 用列表的形式全部打出:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print list(all_files(&amp;#39;*.pye&amp;#39;, os.environ[&amp;#39;PATH&amp;#39;]))&lt;/span&gt;&lt;br&gt;&lt;br&gt;我经常在main方法中使用all_file,来打印在PATH中的满足模式的所有文件名,它不仅能获得首先发现的,也能发现其它的:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import sys&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len( sys.argv) != 2 or sys.argv[1].startswith(&amp;#39;-&amp;#39;):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Use: %s &amp;lt;pattern&amp;gt;&amp;#39; % sys.argv[0]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sys.exit(1)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; matches = list(all_files(sys.argv[1], os.environ[&amp;#39;PATH&amp;#39;]))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;%d match:&amp;#39; % len(matches)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for match in matches:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print match&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;glob.glob(pathname)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return a list of paths matching a pathname pattern. &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The pattern may contain simple shell-style wildcards a la fnmatch.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-474646423201847355?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/474646423201847355/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=474646423201847355' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/474646423201847355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/474646423201847355'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-219.html' title='Python Cookbook 2.19 在给定的路径中查找特定模式的文件'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-871226256799708750</id><published>2007-07-23T10:27:00.001+08:00</published><updated>2007-07-23T10:27:28.554+08:00</updated><title type='text'>Python Cookbook 2.18 在给定的路径中查找文件</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;给定一个路径(一个目录列表,中间有分隔符分割),需要在路径中找到需要的文件.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;基本上,你需要遍历给定的路径:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import os&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def search_file(filename, search_path, pathsep=os.pathsep):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Given a search path, find file with requested name &amp;quot;&amp;quot;&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for path in search_path.split(pathsep):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; candidate =  os.path.join(path, filename)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if os.path.isfile(candidate):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return os.path.abspath(candidate)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return None&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; search_path = &amp;#39;/bin&amp;#39; + os.pathsep + &amp;#39;/usr/bin&amp;#39;&amp;nbsp; # ; on Windows, : on Unix&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; find_file = search_file(&amp;#39;ls&amp;#39;, search_path)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if find_file:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;File &amp;#39;ls&amp;#39; found at %s&amp;quot; % find_file&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;File &amp;#39;ls&amp;#39; not found&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;br&gt;本节讨论的问题是很常见的问题,Python为解决它提供了很多方便.&lt;br&gt;实现搜索的循环还可以写成很多方式,但是一旦找到目标文件,就立刻返回了.在方法最后写的return None并不是必需的,因为在方法的结束是,Python默认会返回一个None.在这里写这一句是让代码看起来更清晰.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; 相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;os.path.isfile(path)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Test whether a path is a regular file&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;os.path.abspath(path)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return the absolute version of a path. &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-871226256799708750?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/871226256799708750/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=871226256799708750' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/871226256799708750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/871226256799708750'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-218.html' title='Python Cookbook 2.18 在给定的路径中查找文件'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4148082958146163990</id><published>2007-07-20T11:17:00.001+08:00</published><updated>2007-07-20T11:17:28.125+08:00</updated><title type='text'>Python Cookbook 2.17 替换目录树下文件的扩展名</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要对一个目录树的文件进行重命名操作,用给定的扩展名替换它们的扩展名.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;对一个目录树下的所有文件进行操作,使用Python标准库的os.walk是比较方便的:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import os&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def swapextensions(dir, before, after):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if before[:1] != &amp;#39;.&amp;#39;: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; before = &amp;#39;.&amp;#39;+before&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; thelen = -len(before)&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if after[:1] != &amp;#39;.&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; after = &amp;#39;.&amp;#39;+after&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for path, subdirs, files in os.walk(dir):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for oldfile in files: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if oldfile[thelen:] == before:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; oldfile =  os.path.join(path, oldfile)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newfile = oldfile[:thelen] + after&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; os.rename(oldfile, newfile)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _==&amp;#39;_ _main_ _&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; import sys&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len(sys.argv) != 4:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;Usage: swapext rootdir before after&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sys.exit(100)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; swapextensions(sys.argv[1], sys.argv[2],  sys.argv[3])&lt;/span&gt;&lt;br&gt;&lt;br&gt;上面的代码说明了如何替换指定目录树下所有文件的扩展名,用于需要批量更新文件名的地方很合适,比如网站.也可以用于更改用批处理下载的文件名称的错误.&lt;br&gt;上面的代码也被设计成模块,以便别的程序使用,或者通过命令行,它是与平台无关的.你可以传递给它传递带.或者不带.的参数,因为在代码中进行了处理.(当然,这也带来一个负面效果,它不能处理不带任何扩展名的文件,尤其是在类Unix系统下)&lt;br&gt; 上面的代码中使用的默写技术可能让理想主义者认为底层.它直接操作了文件名,而不是使用os.path下面的方法.其实并没有关系,因为Python提供的字符串处理功能也是很方便的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;rename(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rename(old, new)&lt;br&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Rename a file or directory.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;join(a, *p)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Join two or more pathname components, inserting &amp;quot;\&amp;quot; as needed&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4148082958146163990?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4148082958146163990/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4148082958146163990' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4148082958146163990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4148082958146163990'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-217.html' title='Python Cookbook 2.17 替换目录树下文件的扩展名'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-9129634317853563303</id><published>2007-07-19T13:00:00.001+08:00</published><updated>2007-07-19T13:00:10.658+08:00</updated><title type='text'>Python Cookbook 2.16 遍历目录树</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;需要检查一个目录,或者以特定目录为跟的目录树,对树中的每一个匹配的文件或目录进行操作.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;Python的标准模块os中提供的生成器os.walk就是为这个需求设计的.我们也可以封装它来实现自己的需求:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import os, fnmatch&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def all_files(root, patterns=&amp;#39;*&amp;#39;, single_level=False, yield_folders=False): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Expand patterns from semicolon-separated string to list&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; patterns =  patterns.split(&amp;#39;;&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for path, subdirs, files in os.walk(root):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if yield_folders:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; files.extend(subdirs) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; files.sort( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for name in files:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for pattern in patterns:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if fnmatch.fnmatch(name, pattern):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield os.path.join(path, name)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if single_level:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break&lt;/span&gt;&lt;br&gt;&lt;br&gt;标准库提供的os.walk是灵活 ,强大而且易用的.不过,正是因为它是标准的,所以它不够灵活,比如它不能选择特定类型的文件,或者以排序模式访问文件,或者只访问单层目录,而不是目录树等.本节演示了上述的功能如何添加到walk中,它将walk封装到自己写的生成器中,并使用标准库的fnmath来匹配特定类型的文件,如果要匹配多个类型,用分号分隔. &lt;br&gt;举例说明,你要获得/tmp目录下所有的Python和HTML文件,包括子目录,可以这样写:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thefiles = list(all_files(&amp;#39;/tmp&amp;#39;, &amp;#39;*.py;*.htm;*.html&amp;#39;))&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果你只是想一次一个的处理,可以不用构造一个列表,用循环就可以了:&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;for path in all_files(&amp;#39;/tmp&amp;#39;, &amp;#39;*.py;*.htm;*.html&amp;#39;): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print path&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果你使用的平台对大小写敏感,你想使用大小写敏感的模式匹配,可以修改模式字符串,如:&amp;quot;*.[Hh][Tt][Mm][Ll]&amp;quot;而不是&amp;quot;*.html&amp;quot;.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; 相关说明:&lt;/span&gt;&lt;br&gt; &lt;br&gt;&lt;span style="font-weight: bold;"&gt;fnmatch(name, pat)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Test whether FILENAME matches PATTERN.&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Patterns are Unix shell style:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; *&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; matches everything&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ?&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; matches any single character &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [seq]&amp;nbsp;&amp;nbsp; matches any character in seq &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [!seq]&amp;nbsp; matches any char not in seq&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; An initial period in FILENAME is not special.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Both FILENAME and PATTERN are first case-normalized&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if the operating system requires it.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If you don&amp;#39;t want this, use fnmatchcase(FILENAME, PATTERN). &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;需要区别os.walk和os.path.walk!&lt;/span&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-9129634317853563303?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/9129634317853563303/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=9129634317853563303' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/9129634317853563303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/9129634317853563303'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-216.html' title='Python Cookbook 2.16 遍历目录树'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-1096305753324941421</id><published>2007-07-18T11:32:00.001+08:00</published><updated>2007-07-18T11:32:28.353+08:00</updated><title type='text'>Python Cookbook 2.15 适配(Adapting)类文件对象到文件对象</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要传递一个&amp;quot;类文件&amp;quot;(file like)对象(如urllib.nrlopen的返回值)到一个只接收文件对象为参数的方法中(如marshal.load).&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;为了适应类型检查,你需要将类文件对象的内容写入临时文件中,然后再操作这个临时文件,下面的代码实现了这个想法: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import types, tempfile&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;CHUNK_SIZE = 16 * 1024&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; def adapt_file(fileObj):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if isinstance(fileObj, file): return fileObj&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; tmpFileObj = tempfile.TemporaryFile&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while True:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data =  fileObj.read(CHUNK_SIZE)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not data: break&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmpFileObj.write (data)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fileObj.close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; tmpFileObj.seek(0)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return tmpFileObj&lt;/span&gt;&lt;br&gt;&lt;br&gt;本节讲了一个罕见的用Python使用适配器模式的例子(你拥有X但需要用Y来做).设计模式是面向对象中对常考虑的问题,大多通过写类来实现,而本质上并不需要它们.在本节中,我们不需要引入新的类,因为adapt_file方法已经能很好的完成我们的需求,因为,我们尊重&lt;font size="-1"&gt;奥卡姆剃刀原则(Occam&amp;#39;s Razor) &lt;/font&gt; ,不引不必要的项目.&lt;br&gt;在使用适配器的时候,各方面都要考虑到,当请优先检查类型,即使要使用一些低级的工具或者方法.考虑好要用什么适配为什么类型,总比用时报出异常要好.这样,你的代码能更灵活,而且重用性更好.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; 奥卡姆剃刀（Occam&amp;#39;s Razor, Ockham&amp;#39;s Razor）&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 是由14世纪逻辑学家、圣方济各会修士奥卡姆的威廉（William of Occam）提出的一个原理。奥卡姆（Ockham）在英格兰的萨里郡，那是他出生的地方。&lt;br&gt;　　这个原理称为"如无必要，勿增实体"（Entities should not be multiplied unnecessarily）.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 人们常常引用奥卡姆剃刀的一个强形式，叙述如下： &lt;br&gt;&lt;br&gt;　　如果你有两个原理，它们都能解释观测到的事实，那么你应该使用简单的那个，直到发现更多的证据。&lt;br&gt;　　对于现象最简单的解释往往比较复杂的解释更正确。&lt;br&gt;　　如果你有两个类似的解决方案，选择最简单的。&lt;br&gt;　　需要最少假设的解释最有可能是正确的。&lt;br&gt;&lt;br&gt;　　……或者以这种自我肯定的形式出现：&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt; 　　让事情保持简单！&lt;/span&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-1096305753324941421?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/1096305753324941421/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=1096305753324941421' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1096305753324941421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1096305753324941421'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-215-adapting.html' title='Python Cookbook 2.15 适配(Adapting)类文件对象到文件对象'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-8571888038286135418</id><published>2007-07-18T11:03:00.001+08:00</published><updated>2007-07-18T11:03:49.359+08:00</updated><title type='text'>Python Cookbook 2.14 重定位到输入文件到文件头</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你构造了一个文件对象(从网络或者文件句柄中读数据),需要定位到文件头,以便读取它的信息.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;将文件操作封装到一个类里面:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;from cStringIO import StringIO &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;class RewindableFile(object):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Wrap a file handle to allow seeks back to the beginning. &amp;quot;&amp;quot;&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def _ _init_ _(self, input_file):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Wraps input_file into a file-like object with rewind. &amp;quot;&amp;quot;&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.file = input_file&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.buffer_file = StringIO( ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.at_start = True&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.start = input_file.tell( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; except (IOError, AttributeError):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.start = 0&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._use_buffer = True&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; def seek(self, offset, whence=0):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Seek to a given byte position.&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Must be: whence == 0 and offset == self.start&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if whence != 0:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise ValueError(&amp;quot;whence=%r; expecting 0&amp;quot; % (whence,))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if offset != self.start:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise ValueError(&amp;quot;offset=%r; expecting %s&amp;quot; % (offset, self.start))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.rewind( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def rewind(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Simplified way to seek back to the beginning. &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.buffer_file.seek(0)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.at_start = True&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def tell(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Return the current position of the file (must be at start).&amp;nbsp; &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not self.at_start:&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise TypeError(&amp;quot;RewindableFile can&amp;#39;t tell except at start of file&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self.start&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def _read(self, size):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if size &amp;lt; 0:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # read all the way to the end of the file &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; y = self.file.read( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self._use_buffer: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.buffer_file.write(y)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self.buffer_file.read ( ) + y&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elif size == 0:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # no need to actually read the empty string&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &amp;quot;&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x = self.buffer_file.read(size)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if len(x) &amp;lt; size:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; y = self.file.read(size - len(x))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self._use_buffer:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.buffer_file.write(y)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return x + y&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return x&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def read(self, size=-1): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Read up to &amp;#39;size&amp;#39; bytes from the file.&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Default is -1, which means to read to end of file.&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x = self._read(size)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self.at_start and x:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  self.at_start = False&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._check_no_buffer( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return x &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def readline(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot; Read a line from the file. &amp;quot;&amp;quot;&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Can we get it out of the buffer_file?&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; s = self.buffer_file.readline ( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if s[-1:] == &amp;quot;\n&amp;quot;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return s&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # No, so read a line from the input file&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; t = self.file.readline ( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self._use_buffer:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.buffer_file.write (t)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._check_no_buffer( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return s + t&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def readlines(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot;read all remaining lines from the file&amp;quot;&amp;quot;&amp;quot; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self.read( ).splitlines(True)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def _check_no_buffer(self): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # If &amp;#39;nobuffer&amp;#39; has been called and we&amp;#39;re finished with the buffer file,&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # get rid of the buffer, redirect everything to the original input file.&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not self._use_buffer and \&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.buffer_file.tell( ) == len(self.buffer_file.getvalue( )):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # for top performance, we rebind all relevant methods in self &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for n in &amp;#39;seek tell read readline readlines&amp;#39;.split( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; setattr(self, n, getattr(self.file, n, None))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; del self.buffer_file&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; def nobuffer(self):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&amp;quot;&amp;quot;tell RewindableFile to stop using the buffer once it&amp;#39;s exhausted&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self._use_buffer = False&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;有时,从网络或文件句柄中读取的数据并不是我们所期望的.比如,你从一个有问题的服务器读数据,本来应该返回XML流,可是它返回了一些没有格式的错误消息.(这种情况很常见,因为很多服务器并没有很好的处理异常输入情况). &lt;br&gt;本节的RewindableFile类可以帮助你解决这个问题,r = RewindableFile(f) 将原始的输入流 f 封装到一个&amp;quot;可重定位的文件&amp;quot;对象 r 中,并提供了缓冲区功能.对 r 的读操作被转发给 f ,数据先保存到了缓冲区,然后返回给调用者,而缓冲区里面保存了所有的数据.&lt;br&gt;r 可以调用rewind方法,即能重定位到文件头,下一次的读操作将首先从缓冲区中读数据,读完后,再从输入流读,而新读入的数据也会添加到缓冲区中. &lt;br&gt;当不需要缓冲区的时候,我们调用 r 的nobuffer方法来释放它.也就是说,当我们读完数据的时候,可以调用这个方法来释放缓冲区,当调用nobuffer后,seek就没有意义了.&lt;br&gt;举例说明,你要访问的服务器会返回错误信息:ERROR:can&amp;#39;t do that,或者XML信息,&amp;lt;?xml...:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: rgb(204, 0, 0);"&gt; import RewindableFile &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; infile = urllib2.urlopen(&amp;quot;&lt;a href="http://somewhere/"&gt;http://somewhere/&lt;/a&gt;&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; infile = RewindableFile.RewindableFile(infile)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; s = infile.readline( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; if s.startswith(&amp;quot;ERROR:&amp;quot;):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise Exception(s[:-1])&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; infile.seek(0)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; infile.nobuffer( )&amp;nbsp;&amp;nbsp; # Don&amp;#39;t buffer the data any more&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ... process the XML from infile ...&lt;/span&gt;&lt;br&gt;&lt;br&gt;在本节中,一个常用的Python技巧不适用了:你不能够很好的隐藏RewindableFie的绑定方法(如果你不知道什么是绑定方法,那没有关系,这样的话,你更不可能将它们隐藏起来).这个问题的原因是,当缓冲区是空的时,RewindableFile重新对read,readline等方法进行赋值,并将它们做为self对象的一个变量.比起使用不常用的隐藏绑定方法技巧 ,这样做性能会好一些.&lt;br&gt;tell方法用于获得当前文件指针的位置,它只能在封装完RewindalbeFile后调用,而且在进行读操作之前.RewindableFile实现的tell方法获得封装后的文件的真实位置,并将它做为起始位置.如果封装的文件对象不支持tell,那么RewindableFile类的tell实现将返回0.&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-8571888038286135418?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/8571888038286135418/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=8571888038286135418' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8571888038286135418'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8571888038286135418'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-214.html' title='Python Cookbook 2.14 重定位到输入文件到文件头'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-8328972247997250991</id><published>2007-07-17T10:39:00.001+08:00</published><updated>2007-07-17T10:39:19.564+08:00</updated><title type='text'>算法学习:用Horner算法计算多项式求和</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;计算表达式,&lt;br&gt;a0 + a1 * x + a2 * x^2 + a3 * x^3 + ... + an * x^n&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;解法:&lt;/span&gt;&lt;br&gt;&lt;br&gt;使用Horner算法解答:&lt;br&gt;&lt;br&gt;原式 = a0 + x(a1 + x(a2 + x(a3 + ...x(an)...)) &lt;br&gt;&lt;br&gt;result &amp;lt;-- a[n]&lt;br&gt;i &amp;lt;-- n&lt;br&gt;while i &amp;gt;= 0&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; result &amp;lt;-- reslut&amp;nbsp; * x&amp;nbsp; +&amp;nbsp; a[i]&lt;br&gt;&amp;nbsp; &amp;nbsp; i &amp;lt;-- i - 1&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;Python描述:&lt;/span&gt;&lt;br&gt;&lt;br&gt;def Horner(a, n, x): &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = a[n]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i = n - 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while i &amp;gt;= 0:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = result * x + a[i]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i -= 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-8328972247997250991?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/8328972247997250991/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=8328972247997250991' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8328972247997250991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8328972247997250991'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/horner.html' title='算法学习:用Horner算法计算多项式求和'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4912556595843641130</id><published>2007-07-17T09:53:00.001+08:00</published><updated>2007-07-17T09:53:47.663+08:00</updated><title type='text'>Python Cookbook 2.13 使用类C++的流操作语法</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你喜欢C++操作I/O的方式,使用操作符(不同的对象对输入其的数据有不同的处理)来处理,也想在Python这样做.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;Python允许你重载操作符,通过重写特定的方法(特定方法指那些命名中以两个下划线开始和结束的方法).要使用&amp;lt;&amp;lt;做为输出,就像C++中那样,需要定义一个输出流操作类并定义函数__lshift__: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;class IOManipulator(object):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def _ _init_ _(self, function=None):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.function = function&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def do(self, output):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.function(output)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def do_endl(stream):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stream.output.write (&amp;#39;\n&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stream.output.flush( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;endl = IOManipulator(do_endl) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;class OStream(object):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def _ _init_ _(self, output=None):&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if output is None:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; import sys&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output = sys.stdout&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.output = output&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.format = &amp;#39;%s&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def _ _lshift_ _(self, thing):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39; the special method which Python calls when you use the &amp;lt;&amp;lt;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operator and the left-hand operand is an OStream &amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if isinstance(thing, IOManipulator):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; thing.do (self)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.output.write(self.format % thing) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.format = &amp;#39;%s&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return self&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def example_main( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout = OStream( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout&amp;lt;&amp;lt; &amp;quot;The average of &amp;quot; &amp;lt;&amp;lt; 1 &amp;lt;&amp;lt; &amp;quot; and &amp;quot; &amp;lt;&amp;lt; 3 &amp;lt;&amp;lt; &amp;quot; is &amp;quot; &amp;lt;&amp;lt; (1+3)/2 &amp;lt;&amp;lt;endl&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;# emits The average of 1 and 3 is 4&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if _ _name_ _ == &amp;#39;_ _main_ _&amp;#39;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; example_main( )&lt;/span&gt;&lt;br&gt;&lt;br&gt;封装Python的类文件对象来模拟C++操作是比较容易的,本节讲了如果用&amp;lt;&amp;lt;来实现插入操作.本节也实现了一个IOManipulator类(向C++中一样)来实现对流的任意插入操作,也预定义了endl(猜猜从哪里来的?)来实现换行和刷新缓冲区.&lt;br&gt;在类OStream的实例中,我们保留了一个format属性, 并在每次调用sys.stdout.write后,将其值设置为默认的&amp;#39;%s&amp;#39;,这样做是因为你可以构造自己需要的流输出格式,如:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def do_hex(stream):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stream.format  = &amp;#39;%x&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;hex = IOManipulator(do_hex)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;cout &amp;lt;&amp;lt; 23 &amp;lt;&amp;lt; &amp;#39; in hex is &amp;#39; &amp;lt;&amp;lt; hex &amp;lt;&amp;lt; 23 &amp;lt;&amp;lt; &amp;#39;, and in decimal &amp;#39; &amp;lt;&amp;lt; 23 &amp;lt;&amp;lt; endl &lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0); font-style: italic;"&gt;# 输出 23 in hex is 17, and in decimal 23&lt;/span&gt;&lt;br&gt;&lt;br&gt;有些人喜欢C++的cout&amp;lt;&amp;lt;something写法,有些人不喜欢.在Python中,我们可以使用更简单和可读的代码:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; print&amp;gt;&amp;gt;somewhere, &amp;quot;The average of %d and %d is %f\n&amp;quot; % (1, 3, (1+3)/2)&lt;/span&gt;&lt;br&gt;&lt;br&gt;这是Python方式的写法(和C很像).一切都取决于你更多使用C++还是C.不过无论怎样,本节都给出了选则方案,即使你不会使用本节讨论的内容,也能从其中看到在Python中进行操作符重载是很简单和方便的.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4912556595843641130?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4912556595843641130/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4912556595843641130' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4912556595843641130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4912556595843641130'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-213-c.html' title='Python Cookbook 2.13 使用类C++的流操作语法'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-8289843867293831198</id><published>2007-07-17T09:29:00.001+08:00</published><updated>2007-07-17T09:29:16.583+08:00</updated><title type='text'>Python Cookbook 2.12 在windows平台下向stdout输出二进制数据</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;需要输出二进制数据(如,一个图像)到windows平台的标准输出.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;这里可以使用setmode函数,它位于Python中依赖平台(windows)的msvcrt模块中,用法如下: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import sys&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if sys.platform == &amp;quot;win32&amp;quot;:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; import os, msvcrt&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; msvcrt.setmode(sys.stdout.fileno( ), os.O_BINARY)&lt;/span&gt;&lt;br&gt;&lt;br&gt;现在你就可以调用sys.stdout.write向标准输出输出任意二进制数据.&lt;br&gt;在类Unix系统中,不会(也不需要)区分二进制文件和文本文件,然而在windows平台上,如果你要输出图像文件, 必须以二进制方式打开.而在Python中,sys.stdout文件对象默认的打开方式是文本模式,所以你需要做如上处理.&lt;br&gt;你可以让Python以二进制模式打开标准输出,通过给命令行解释器添加&amp;#39;-u&amp;#39;参数.比如,你的CGI脚本运行在Apache服务器下,在你的代码的第一行,可以这样写:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;#! c:/python23/python.exe -u &lt;/span&gt;&lt;br&gt;&lt;br&gt;在Python2.3后的安装版本下,上面的方式是可以工作的.问题是,你并不是总是能预计你的脚本会工作在哪个版本的Python下,所以本节开始给出的方法还是推荐使用的.setmode函数通过msvcrt模块让你能修改标准输出的打开模式,在这种情况下,你能保证是以二进制模式打开sys.stdout的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt; &lt;br&gt;&lt;span style="font-weight: bold;"&gt;sys.stdout.fileno(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fileno() -&amp;gt; integer &amp;quot;file descriptor&amp;quot;.&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This is needed for lower-level file interfaces, such os.read().&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-8289843867293831198?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/8289843867293831198/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=8289843867293831198' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8289843867293831198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8289843867293831198'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-212-windowsstdout.html' title='Python Cookbook 2.12 在windows平台下向stdout输出二进制数据'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-1459051157219588394</id><published>2007-07-16T10:35:00.001+08:00</published><updated>2007-07-16T10:35:10.446+08:00</updated><title type='text'>Python Cookbook 2.11 打包目录树中的文件到压缩文件</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你需要打包一个目录下的所有文件(包括子目录)到压缩文件中去,压缩的方法可以使用流行的gzip方法或者压缩比更高的bzip2方法.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;Python标准库中的tarfile模块就支持上述的两种方式:你只需要指出自己需要的方法,将它做为参数传递给tarfile.TarFile.open方法即可 ,如:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import tarfile, os&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def make_tar(folder_to_backup, dest_folder, compression=&amp;#39;bz2&amp;#39;):&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if compression:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dest_ext = &amp;#39;.&amp;#39; + compression&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dest_ext = &amp;#39;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; arcname = os.path.basename(folder_to_backup)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dest_name = &amp;#39;%s.tar%s&amp;#39; % (arcname, dest_ext)&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dest_path = os.path.join(dest_folder, dest_name)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if compression: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dest_cmp = &amp;#39;:&amp;#39; + compression&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dest_cmp = &amp;#39;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; out = tarfile.TarFile.open(dest_path, &amp;#39;w&amp;#39;+dest_cmp)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; out.add(folder_to_backup, arcname)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; out.close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; return dest_path&lt;/span&gt;&lt;br&gt;&lt;br&gt;你也可以传递&amp;#39;gz&amp;#39;做为open的第二个参数,来使用gzip方式压缩文件,而非默认的bzip2方式,或者传递&amp;#39;&amp;#39;从而不使用任何压缩方式.生成文件的扩展名是通过tarfile.TarFile.open的第二个参数来决定的,可以是.tar,.tar.gz,或者.tar.bz2,对应的参数为:&amp;#39;w&amp;#39;,&amp;#39;w:gz&amp;#39;和&amp;#39;w:bz2&amp;#39;. &lt;br&gt;除了open之外,类tarfile.TarFile也提供了其它的类方法,你可以使用适合的来生成实例.我认为open是最方便的,因为它使用open的模式参数来表示压缩方式,当然,如果你希望无条件的使用bz2方法,也可以使用bz2open来代替.&lt;br&gt;一旦我们拥有了tarfile.TarFile的实例,并且设置了适当的压缩方式,剩下的工作都可以交给add方法来完成.在实际中,如果fold_to_backup是一个目录,而不是一个特定的文件, add会递归添加该目录下所有的文件.有些情况下,我们想控制添加的方式,可以传递给add第二个参数recursive=False来关掉递归方式.当add完成后,make_tar方法剩下的工作就是关闭文件,和返回压缩后文件的路径,这样是为了给调用者更多的信息.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; open(cls, name=None, mode=&amp;#39;r&amp;#39;, fileobj=None, bufsize=10240)&lt;/span&gt; method of __builtin__.type instance&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Open a tar archive for reading, writing or appending. Return&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; an appropriate TarFile class.&lt;br&gt;&lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; mode:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;r&amp;#39; or &amp;#39;r:*&amp;#39; open for reading with transparent compression&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;r:&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open for reading exclusively uncompressed&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;r:gz&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open for reading with gzip compression &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;r:bz2&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open for reading with bzip2 compression&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;a&amp;#39; or &amp;#39;a:&amp;#39;&amp;nbsp; open for appending&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;w&amp;#39; or &amp;#39;w:&amp;#39;&amp;nbsp; open for writing without compression&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;w:gz&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open for writing with gzip compression &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;w:bz2&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open for writing with bzip2 compression&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;r|*&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open a stream of tar blocks with transparent compression&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;r|&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open an uncompressed stream of tar blocks for reading &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;r|gz&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open a gzip compressed stream of tar blocks&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;r|bz2&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open a bzip2 compressed stream of tar blocks&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;w|&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open an uncompressed stream for writing&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;w|gz&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open a gzip compressed stream for writing &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;w|bz2&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; open a bzip2 compressed stream for writing&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-1459051157219588394?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/1459051157219588394/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=1459051157219588394' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1459051157219588394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/1459051157219588394'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-211.html' title='Python Cookbook 2.11 打包目录树中的文件到压缩文件'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-2124597040136752535</id><published>2007-07-16T10:10:00.001+08:00</published><updated>2007-07-16T10:10:32.008+08:00</updated><title type='text'>Python Cookbook 2.10 处理内存中的zip文件</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;你的程序接收到一个字符串,里面包含了一个zip文件的内容,你需要获得这些信息.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;对于这一类问题,使用标准库的cStringIO最合适:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import cStringIO, zipfile &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;class ZipString(ZipFile):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def _ _init_ _(self, datastring):&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ZipFile._ _init_ _(self, cStringIO.StringIO(datastring))&lt;/span&gt;&lt;br&gt;&lt;br&gt;这样的问题会经常遇到,比如从数据库中的BLOB字段读取zip文件,或者从网络连接中读取.以前的时候,可以使用临时文件,用zipfile处理完数据后,要保证临时文件被删除;后来使用了cStringIO后,就再也没有使用过临时文件了. &lt;br&gt;&lt;br&gt;cStringIO模块能够让你以文件的方式来访问字符串.另外,你也可以将数据以文件的方式写入cStringIO的实例,然后获得一个包含文件内容的字符串.大部分能处理file对象的Python模块并不检查你处理的对象是否真正是文件对象,只要是&amp;quot;类文件&amp;quot;对象就可以了.这些模块只是在需要的时候调用文件操作的方法,只要类文件对象提供类似的接口和适当的返回值,一切都没有问题.这就说明的多态的强大,以至于你几乎不需要写任何类型测试的代码(比如,if type(x) is y,或者if isinstance(x,y)).一些比较底层的模块,如marshl,需要使用真正的file对象,而zipfile是不需要的,所以我们的代码才能如此简单. &lt;br&gt;如果你使用的Python版本不是C语言版本,通常被成为&amp;quot;CPython&amp;quot;,那你在标准库中可能没有cStringIO模块.以c开头的模块,暗示是以C语言实现的模块,它们能优化代码的效率,但是不保证所有的Python版本都通用.当然,一些别的版本的Python也提供了相关的模块.(如Jython,用java实现的版本并运行在jvm上,PyPy,用Python实现机器码,还有IronPython,用C#实现的,可以运行在.Net  CLR环境里面).不用太担心,Python标准库总是提供了用标准Python实现的模块StringIO,它和cStringIO具有相同的实现(只是没有cStringIO效率高),你只需要修改import语句,让它能在cStringIO不存在的时候正确引用StringIO,比如:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import zipfile&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;try:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; from cStringIO import StringIO&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; except ImportError:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; from StringIO import StringIO&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;class ZipString(ZipFile): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def _ _init_ _(self, datastring):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ZipFile._ _init_ _(self, StringIO(datastring)) &lt;/span&gt;&lt;br&gt;&lt;br&gt;这样修改的话,本节的代码就能在Jython或者其它版本的Python中运行了.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;StringIO(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; StringIO([s]) -- Return a StringIO-like stream for reading or writing &lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-2124597040136752535?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/2124597040136752535/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=2124597040136752535' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2124597040136752535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2124597040136752535'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-210-zip.html' title='Python Cookbook 2.10 处理内存中的zip文件'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-4470892525055079005</id><published>2007-07-11T17:51:00.001+08:00</published><updated>2007-07-11T17:51:58.441+08:00</updated><title type='text'>Python Cookbook 2.9 从Zip文件中读数据</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;不解压缩zip文件,实现对文件内容的获取.&lt;br&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;zip文件是比较流行的压缩文件的方式,它也是跨平台的.标准Python库提供了zipfile模块来简化相关的操作:&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;import zipfile&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;z = zipfile.ZipFile(&amp;quot;zipfile.zip&amp;quot;, &amp;quot;r&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;for filename in z.namelist ( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;File:&amp;#39;, filename,&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bytes = z.read(filename) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;has&amp;#39;, len(bytes), &amp;#39;bytes&amp;#39;&lt;/span&gt;&lt;br&gt;&lt;br&gt;Python可以直接操作zip文件中的数据,可以获得文件列表或者直接获得文件的内容.本节中给出的例子获得了zipfile.zip中的文件列表和包含文件的长度 .&lt;br&gt; Python目前还不能处理分卷压缩的zip文件和带有注释的zip文件.需要注意的时候,打开zip文件时要使用&amp;#39;r&amp;#39;参数而不是&amp;#39;rb&amp;#39;,尽管后者看起来更合理一些(尤其在windows系统下).因为在ZipFile下面,并不识别&amp;#39;rb&amp;#39;选项,这个和open是不同的.&amp;#39;r&amp;#39;选项就表示了是对zip文件进行读操作.&lt;br&gt;假如一个zip文件包含了zip模块(py或者pyw文件),你可以在sys.path中添加这个文件的路径 ,并能使用import来引用zip文件中的模块.下面是一个小例子,仅仅用来说明问题,它创建一个zip文件,应引用了它,最后再删除:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import zipfile, tempfile, os, sys&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; handle, filename = tempfile.mkstemp(&amp;#39;.zip&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;os.close(handle)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; z = zipfile.ZipFile(filename, &amp;#39;w&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;z.writestr(&amp;#39;hello.py&amp;#39;, &amp;#39;def f( ): return &amp;quot;hello world from &amp;quot;+_ _file_ _\n&amp;#39;) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;z.close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;sys.path.insert(0, filename)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;import hello&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;print hello.f( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; os.unlink(filename)&lt;/span&gt;&lt;br&gt;&lt;br&gt;用执行这个例子后输出:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;hello world from /tmp/tmpESVzeY.zip/hello.py&lt;/span&gt;&lt;br&gt;&lt;br&gt;除了说明Python能从zip中引入文件外,这个例子也说明如何创建(并删除)一个临时文件,而且也说明了如何使用writestr来给zip文件添加一个文件,而不是先在磁盘上创建一个. &lt;br&gt;需要注意的是,import引入的文件路径类似一个目录(在本例中是/tmp/tmpESVzeY.zip/hello.py,因为我们使用的是临时文件,所以不同时刻和不同系统下运行的结果可能是不一样的),特别的,全局变量__file__,它表示了/tmp/tmpESVzeY.zip/hello.py,具有一个类似与目录结构的路径,当然,实际上它并不是目录结构的,你用open方法是不能这样打开zip中的文件的.要想打开zip中的文件,要使用zipfile. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;z = ZipFile(file, mode=&amp;quot;r&amp;quot;, compression=ZIP_STORED, allowZip64=True)&lt;/span&gt;&lt;br&gt;&amp;nbsp;|&amp;nbsp; &lt;br&gt;&amp;nbsp;|&amp;nbsp; file: Either the path to the file, or a file-like object. &lt;br&gt;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If it is a path, the file will be opened and closed by ZipFile.&lt;br&gt;&amp;nbsp;|&amp;nbsp; mode: The mode can be either read &amp;quot;r&amp;quot;, write &amp;quot;w&amp;quot; or append &amp;quot;a&amp;quot;.&lt;br&gt;&amp;nbsp;|&amp;nbsp; compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib). &lt;br&gt;&amp;nbsp;|&amp;nbsp; allowZip64: if True ZipFile will create files with ZIP64 extensions when&lt;br&gt;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; needed, otherwise it will raise an exception when this would&lt;br&gt;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; be necessary.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; mkstemp(suffix=&amp;#39;&amp;#39;, prefix=&amp;#39;tmp&amp;#39;, dir=None, text=False)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mkstemp([suffix, [prefix, [dir, [text]]]])&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; User-callable function to create and return a unique temporary&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; file.&amp;nbsp; The return value is a pair (fd, name) where fd is the &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; file descriptor returned by os.open, and name is the filename.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If &amp;#39;suffix&amp;#39; is specified, the file name will end with that suffix,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; otherwise there will be no suffix.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If &amp;#39;prefix&amp;#39; is specified, the file name will begin with that prefix, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; otherwise a default prefix is used.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If &amp;#39;dir&amp;#39; is specified, the file will be created in that directory,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; otherwise a default directory is used.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If &amp;#39;text&amp;#39; is specified and true, the file is opened in text &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mode.&amp;nbsp; Else (the default) the file is opened in binary mode.&amp;nbsp; On&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; some operating systems, this makes no difference.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The file is readable and writable only by the creating user ID.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If the operating system uses permission bits to indicate whether a &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; file is executable, the file is executable by no one. The file&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; descriptor is not inherited by children of this process.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Caller is responsible for deleting the file when done with it.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; writestr(self, zinfo_or_arcname, bytes)&lt;/span&gt; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unbound zipfile.ZipFile method&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Write a file into the archive.&amp;nbsp; The contents is the string&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;bytes&amp;#39;.&amp;nbsp; &amp;#39;zinfo_or_arcname&amp;#39; is either a ZipInfo instance or &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; the name of the file in the archive.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-4470892525055079005?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/4470892525055079005/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=4470892525055079005' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4470892525055079005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/4470892525055079005'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-29-zip.html' title='Python Cookbook 2.9 从Zip文件中读数据'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-477395421642107693</id><published>2007-07-11T10:07:00.001+08:00</published><updated>2007-07-11T10:07:39.713+08:00</updated><title type='text'>Python Cookbook 2.8 使用随机方式修改</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;要从一个大的二进制文件中读取 一块数据,修改完成后,要写回文件.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;打开文件,做必要的偏移计算,读取数据,处理完后,重新定位到数据偏移处,写入数据即可.看代码吧,比说的更清楚一些:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import struct&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;format_string = &amp;#39;8l&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # e.g., say a record is 8 4-byte integers&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; thefile = open(&amp;#39;somebinfile&amp;#39;, &amp;#39;r+b&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;record_size = struct.calcsize(format_string)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; thefile.seek(record_size * record_number)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;buffer = thefile.read(record_size)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; fields = list(struct.unpack(format_string, buffer))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;# Perform computations, suitably modifying fields, then:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;buffer = struct.pack(format_string, *fields)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thefile.seek(record_size * record_number)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;thefile.write(buffer)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thefile.close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;这种方式只有在二进制文件的数据块是固定大小的时候适用,对于一般的文本文件不适用,另外, 数据库的大小要和struct中定义的一样.代码中的struct的典型定义&amp;#39;8l&amp;#39;,表示每一个字段是8个4字节的整数构成,它们都是有符号整数类型,被转换为Python的int型数据.这样,上面的代码中fields表示了8个整数为单位的列表.需要注意的是unpack返回的是一个元组,而元组是不可修改的,所以要将它重新绑定为一个列表,因为列表是可以修改的.但要注意的是,不要修改列表的大小,因为如果你要用struct.pack写回的时候 ,会抛出异常.同样,本节的方法也不适用于文件中数据块大小不固定的情况.&lt;br&gt;当再次定位文件指针的时候,可以不使用seek(record_size * record_number),而使用反向偏移定位:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thefile.seek(-record_size, 1)&lt;/span&gt;&lt;br&gt;&lt;br&gt;其中第二个参数1表示从文件的当前位置开始定位,由于第一个参数是负值, 所以是向前定位了.seek默认是从文件的起始位置开始定位,当然你也可以显示的将第二个参数设置为0.&lt;br&gt;当你调用第一个seek之前,不必再次调用open打开文件,同样,也不用在调用完write方法后立刻close它.当你正确打开了文件对象(二进制更新模式,而不是文本模式),你可以任意次数的更新文件,最后再关闭.&lt;br&gt;文件需要以更新模式打开(同时支持读和写),这就是&amp;#39;r+b&amp;#39;的含义:为读和写操作打开文件,并且不做任何隐含的转换,因为是二进制模式的.(&amp;#39;b&amp;#39;在Unix和类unix系统上是可选的,不过还是建议加上,当然,在windows系统是,是必须的),如果你只是想创建一个草稿文件,可是仍要做一些读写处理,可以使用&amp;#39;w+b&amp;#39; 做为open的第二个参数.当然,我从来没有见过这么奇怪的需求.二进制文件一般都是先被创建(使用&amp;#39;wb&amp;#39;参数,写数据,然后关闭),再用&amp;#39;r+b&amp;#39;参数打开处理.&lt;br&gt;当然,虽然本节提供的方法只适用于固定数据块大小的二进制文件,也可以适用于更高级的情况:有一个索引文件表示块的大小和位置,这种通过索引文件访问的技术已经不是什么新技术了,可是它还是非常重要的.在今天,虽然人们处理的情况大多数是数据库,文本文件(还包括html,xml等),还有偶尔的固定块大小的二进制文件, 也不能排出遇到使用索引文件的可能性.如果遇到这样的情况,处理的方法和本节是非常类似的,只是块大小和偏移位置不是计算的,而是从索引文件中读取的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;seek(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; seek(offset[, whence]) -&amp;gt; None.&amp;nbsp; Move to new file position. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Argument offset is a byte count.&amp;nbsp; Optional argument whence defaults to&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 (offset from start of file, offset should be &amp;gt;= 0); other values are 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (move relative to current position, positive or negative), and 2 (move &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; relative to end of file, usually negative, although many platforms allow&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; seeking beyond the end of a file).&amp;nbsp; If the file is opened in text mode,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; only offsets returned by tell() are legal.&amp;nbsp; Use of other offsets causes &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; undefined behavior.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Note that not all file objects are seekable.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-477395421642107693?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/477395421642107693/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=477395421642107693' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/477395421642107693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/477395421642107693'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-28.html' title='Python Cookbook 2.8 使用随机方式修改'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-2405050298944873150</id><published>2007-07-10T14:22:00.001+08:00</published><updated>2007-07-10T14:22:29.488+08:00</updated><title type='text'>Python Cookbook 2.7 使用随机方式访问I/O</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;需要访问一个大的二进制文件,并读取指定位置的数据,而不是一个个的读到那里.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;指定的偏移地址等于数据块大小乘以块数.可以以此来定位到指定的数据块,并读取数据.比如,从文件的第七块来读取数据,块大小是48字节:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; thefile = open(&amp;#39;somebinfile&amp;#39;, &amp;#39;rb&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;record_size = 48&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; record_number = 6&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thefile.seek(record_size * record_number)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;buffer =  thefile.read(record_size)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;需要注意的是,块数从0开始计数,所以record_number等于6.&lt;br&gt;&lt;br&gt;上面的方法只适用于固定块大小的二进制文件,对于一般的文本文件可能就不适用了.在代码中,是以二进制方式打开文件的,只要是以二进制方式打开,你可以随意的seek和read,在关闭文件之前,你不用为了使用seek而再打开它一次. &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;seek(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; seek(offset[, whence]) -&amp;gt; None.&amp;nbsp; Move to new file position.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Argument offset is a byte count.&amp;nbsp; Optional argument whence defaults to &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 (offset from start of file, offset should be &amp;gt;= 0); other values are 1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (move relative to current position, positive or negative), and 2 (move&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; relative to end of file, usually negative, although many platforms allow &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; seeking beyond the end of a file).&amp;nbsp; If the file is opened in text mode,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; only offsets returned by tell() are legal.&amp;nbsp; Use of other offsets causes&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; undefined behavior.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Note that not all file objects are seekable. &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-2405050298944873150?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/2405050298944873150/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=2405050298944873150' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2405050298944873150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2405050298944873150'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-27-io.html' title='Python Cookbook 2.7 使用随机方式访问I/O'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-2226269209804750697</id><published>2007-07-10T10:22:00.001+08:00</published><updated>2007-07-10T10:22:24.234+08:00</updated><title type='text'>Python Cookbook 2.6 处理文件中的每一个单词</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;要对文件中的每一个单词进行处理.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;实现这个需求可以用两层的循环嵌套来实现,一个处理文件中的行,另一个处理行中的单词:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for line in open(thefilepath): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for word in line.split( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dosomethingwith(word)&lt;/span&gt; &lt;br&gt;&lt;br&gt;内层的for语句将单词定义为用空格分隔的字符序列(unix中的wc命令也是这样做的),另外的定义单词的方法,你可以使用正则式:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import re&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;re_word = re.compile (r&amp;quot;[\w&amp;#39;-]+&amp;quot;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for line in open(thefilepath):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for word in re_word.finditer(line): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dosomethingwith(word.group(0))&lt;/span&gt;&lt;br&gt;&lt;br&gt;在这里,单词被定义为由字母,连字符和撇号构成的字符序列.&lt;br&gt;&lt;br&gt;如果你要重新定义单词,那你需要改变正则表达式,而外层的循环是不用改变的.&lt;br&gt;当遇到迭代处理的时候,可以把迭代操作封装到一个迭代对象中,这样的封装可简化代码和操作(使用生成器yield): &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def words_of_file(thefilepath, line_to_words=str.split):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; the_file = open(thefilepath):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for line in the_file:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for word in line_to_words(line):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield word&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; the_file.close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; for word in words_of_file(thefilepath):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dosomethingwith(word)&lt;/span&gt;&lt;br&gt;&lt;br&gt;这种方式让你将问题分开和简化为两个部分:怎样迭代操作对象(本例中是文件中的单词),另一个是怎样处理迭代出的元素.一旦你清晰的封装出迭代操作 (在这里,使用了生成器),剩下的操作就是简单的for循环了.在程序中,可以多次使用这个迭代器,即使在维护代码的时候,也可以只是修改迭代器而不是所有的代码.这个好处类似于人们写一个个的函数而不是到处粘贴代码,在Python中,你可以使用这个技巧来封装循环结构.&lt;br&gt;在上面的代码中,我们在处理完文件后确保它关闭,这是一个良好的做法,也通过使用split方法把行变成了单词.当然,假如我们要使用正则式来定义单词,可是使用下面的&amp;#39;hook&amp;#39;代码来实现: &lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import re&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def words_by_re(thefilepath, repattern=r&amp;quot;[\w&amp;#39;-]+&amp;quot;):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wre = re.compile(repattern)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def line_to_words(line):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for mo in wre.finditer(line):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return mo.group(0)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; return words_of_file(thefilepath, line_to_words)&lt;/span&gt;&lt;br&gt;&lt;br&gt;在上面的代码中,我们同样定义了默认的正则式,当然也运行用户重写,一般情况下,将较通用的属性写成默认值,会增加代码的易用性和通用性.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; re.finditer(pattern, string, flags=0)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return an iterator over all non-overlapping matches in the&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; string.&amp;nbsp; For each match, the iterator returns a match object.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Empty matches are included in the result. &lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-2226269209804750697?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/2226269209804750697/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=2226269209804750697' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2226269209804750697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/2226269209804750697'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-26.html' title='Python Cookbook 2.6 处理文件中的每一个单词'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-7861314472940302198</id><published>2007-07-09T15:08:00.001+08:00</published><updated>2007-07-09T15:08:25.498+08:00</updated><title type='text'>Python Cookbook 2.5 统计文件行数</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;需要统计一个文件的行数.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;最简单的办法是把文件读入一个大的列表中,然后统计列表的长度.如果文件的路径是以参数的形式filepath传递的,那么只用一行代码就可以完成我们的需求了:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; count = len(open(filepath,&amp;#39;rU&amp;#39;).readlines())&lt;/span&gt;&lt;br&gt;&lt;br&gt;如果是非常大的文件,上面的方法可能很慢,甚至失效.此时,可以使用循环来处理:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;count = -1&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; for count, line in enumerate(open(thefilepath, &amp;#39;rU&amp;#39;)):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pass&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; count += 1&lt;/span&gt;&lt;br&gt;&lt;br&gt;另外一种处理大文件比较快的方法是统计文件中换行符的个数&amp;#39;\n&amp;#39;(或者包含&amp;#39;\n&amp;#39;的字串,如在windows系统中):&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;count = 0&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; thefile = open(thefilepath, &amp;#39;rb&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;while True:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; buffer =  thefile.read(8192*1024)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not buffer:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; count += buffer.count(&amp;#39;\n&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;thefile.close( )&lt;/span&gt;&lt;br&gt;&lt;br&gt;参数&amp;#39;rb&amp;#39;是必须的,否则在windows系统上,上面的代码会非常慢. &lt;br&gt;&lt;br&gt;当外部系统提供统计行数的方法时,你可以使用它们(通过os.popen),如unix的wc - l.当然,通过自己的程序来完成会更简单,快捷和通用.你可以假设大多数的文本文件都有合理的大小,所以把它们一次读入内存中处理是可行的.对于这样的情况,len方法返回readlines的大小是最简单的.&lt;br&gt;加入一个文件的大小大于内存(比如,有好几百M那么大),那个最简单的方法会变得难以忍受的慢,因为操作系统要使用虚拟内存,并不停同过硬盘来换页.也可能出现失败的情况 ,就是虚拟内存不够大.一台有256M内存的机器,当处理一个1G或2G大小的文件的时候,仍然可能出现严重的问题.在这种情况下,使用循环处理是比较好的方式,enumerate保存了函数.&lt;br&gt;第三种方法的核心思想是统计缓存中回车换行字符的个数.这可能最不容易直接想到的方法,也是最不通用的方法,但它可能是最快的方法.&lt;br&gt;当然,在大多数情况下,性能并不是最重要的,但如果它是的话,影响性能的部分往往不是我们的直觉告诉我们的地方,所以请千万不要相信自己的直觉, 要考评估和测量来判断.举例说明,对于一个中等大小的unix日志文件,比如一个18M的文本,包含了230,000行:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;[situ@tioni nuc]$ wc nuc&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;231581 2312730 18508908 nuc &lt;/span&gt;&lt;br&gt;&lt;br&gt;使用下面的测试文件,bench.py:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import time&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def timeo(fun, n=10):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; start = time.clock( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in xrange(n): fun( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; stend = time.clock( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; thetime = stend-start&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return fun._ _name_ _, thetime &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import os&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def linecount_w( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return int(os.popen(&amp;#39;wc -l nuc&amp;#39;).read( ).split( )[0])&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def linecount_1( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return len(open(&amp;#39;nuc&amp;#39;).readlines( ))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def linecount_2( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; count = -1&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for count, line in enumerate(open(&amp;#39;nuc&amp;#39;)): pass&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return count+1&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def linecount_3( ):&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; count = 0&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; thefile = open(&amp;#39;nuc&amp;#39;, &amp;#39;rb&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while True: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; buffer = thefile.read(65536)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not buffer: break &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; count += buffer.count(&amp;#39;\n&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return count&lt;/span&gt; &lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for f in linecount_w, linecount_1, linecount_2, linecount_3:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print f._ _name_ _, f( ) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;for f in linecount_1, linecount_2, linecount_3:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;%s: %.2f&amp;quot;%timeo(f) &lt;/span&gt;&lt;br&gt;&lt;br&gt;首先我调用所有的方法来读文件,以确保不会发生异常情况(如果发生的话程序会中止),接下来,在函数timo中,我调用每种方法10次,然后看看结果,这是一个比较旧但比较稳定的机器:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;[situ@tioni nuc]$ python -O bench.py&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;linecount_w 231581&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;linecount_1 231581&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; linecount_2 231581&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;linecount_3 231581&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;linecount_1: 4.84&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;linecount_2: 4.54&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;linecount_3: 5.02&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;br&gt;可以看出,性能上的差别不是很大,实际上,一般用户不会在意10%左 右的性能差别.另外,最快的方法是用循环处理文件对象,而最慢的方法是统计换行符的个数.在实际中,假如不考虑处理那些好几百M的大文件,我总是会选中第一种最简单的方法.&lt;br&gt;测量代码的性能是很重要的,Python标准库也提供了timeit来实现这些工作.我建议你使用timeit,而不是像我在本节做的那样,自己写测试代码,我写的代码是好几年前的事情了,现在既然有了timeit,就没有必要再使用它了.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt; 相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;NAME&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; timeit - Tool for measuring execution time of small code snippets.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;FILE&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; python25\lib\timeit.py&lt;br&gt; &lt;br&gt;&lt;span style="font-weight: bold;"&gt;DESCRIPTION&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This module avoids a number of common traps for measuring execution&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; times.&amp;nbsp; See also Tim Peters&amp;#39; introduction to the Algorithms chapter in&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; the Python Cookbook, published by O&amp;#39;Reilly. &lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Library usage: see the Timer class.&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Command line usage:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement]&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-7861314472940302198?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/7861314472940302198/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=7861314472940302198' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7861314472940302198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/7861314472940302198'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-25.html' title='Python Cookbook 2.5 统计文件行数'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-8204337482485851431</id><published>2007-07-09T10:03:00.001+08:00</published><updated>2007-07-09T10:03:38.592+08:00</updated><title type='text'>Python Cookbook 2.4 在文件中读入指定行</title><content type='html'>&lt;span style="font-weight: bold; color: rgb(0, 0, 0);"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;需要从文件中得到指定行.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;标准库提供的linecache模块提供了解决方案:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;import linecache &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;theline = linecache.getline(thefilepath, desired_line_number)&lt;/span&gt;&lt;br&gt;&lt;br&gt;在处理这一类的问题时,linecache总是可以做为一种方案,尤其是要重复执行的时候,因为linecache提供的机制能防止重复进行一些无用的操作.当你使用完毕的时候 ,调用clearcache方法来清空使用的缓存.也可以使用checkcache确保对文件的修改正确的保存在磁盘上.&lt;br&gt;linecache读入并缓存给出文件的所有内容,所以假如文件非常的巨大,linecache可能要做更多的工作.如果这成为你程序的瓶颈,用循环处理可能会获得更好的效果:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;def getline(thefilepath, desired_line_number): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if desired_line_number &amp;lt; 1: return &amp;#39;&amp;#39;&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for current_line_number, line in enumerate(open(thefilepath, &amp;#39;rU&amp;#39;)): &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if current_line_number == desired_line_number-1: return line&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; return &amp;#39;&amp;#39;&lt;/span&gt;&lt;br&gt;&lt;br&gt;需要注意的地方是enumerate从0开始计数,所以我们要在计算的时候减一.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;class enumerate(object)&lt;/span&gt;&lt;br&gt;&amp;nbsp;|&amp;nbsp; enumerate(iterable) -&amp;gt; iterator for index, value of iterable &lt;br&gt;&amp;nbsp;|&amp;nbsp; &lt;br&gt;&amp;nbsp;|&amp;nbsp; Return an enumerate object.&amp;nbsp; iterable must be an other object that supports&lt;br&gt;&amp;nbsp;|&amp;nbsp; iteration.&amp;nbsp; The enumerate object yields pairs containing a count (from&lt;br&gt;&amp;nbsp;|&amp;nbsp; zero) and a value yielded by the iterable argument.&amp;nbsp; enumerate is useful &lt;br&gt;&amp;nbsp;|&amp;nbsp; for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ...&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-8204337482485851431?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/8204337482485851431/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=8204337482485851431' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8204337482485851431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/8204337482485851431'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-24.html' title='Python Cookbook 2.4 在文件中读入指定行'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-3653821323743027052</id><published>2007-07-06T10:34:00.001+08:00</published><updated>2007-07-06T10:34:14.262+08:00</updated><title type='text'>Python练习:在线更新工具2(07-06)</title><content type='html'>更新一些地方:&lt;br&gt;1.用工具下载curl&lt;br&gt;&lt;a href="http://curl.haxx.se"&gt;curl&lt;/a&gt;比wget更强大一些,也提供了很多开发库,可以方便使用.据说可以实现多线程下载.&lt;br&gt;2.多线程&lt;br&gt;Python的多线程比较简单,需要注意的是要所有的线程都结束了,主程序才能关闭,所以要在主程序中调用子线程的join方法.&lt;br&gt;另,在执行curl的时候,没有直接调用,而是采用的start curl的方法,这样会分别开几个控制台,主程序也能很快的结束. &lt;br&gt;代码如下:&lt;br&gt;&lt;br&gt;import urllib,os,re,threading&lt;br&gt;class UpdateItem:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test.zip,20,c:\temp,&lt;a href="http://www.xxx.com"&gt;http://www.xxx.com&lt;/a&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self,sequence): &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.fileName = sequence[0]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.fileSize = int(sequence[1])&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.filePath = sequence[2]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.url = sequence[3]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.len = 4&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if len(sequence) &amp;gt; 4:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  self.pageUrl = sequence[4]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.regstr = sequence[5]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.len = 6&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __str__(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; str1 = &amp;#39;,&amp;#39;.join((self.fileName,str(self.fileSize),self.filePath,self.url))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if  self.len != 4:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; str1 = &amp;#39;,&amp;#39;.join((str1,self.pageUrl,self.regstr))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return str1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __len__(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return self.len&lt;br&gt;class UrlParse(threading.Thread):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self, item): &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; threading.Thread.__init__(self)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.item = item&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def isNewSize(self, oldsize):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.socket = urllib.urlopen(self.item.url)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; fileSize = int(self.socket.headers[&amp;#39;Content-Length&amp;#39;]) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if oldsize == fileSize:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return False&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.item.fileSize = fileSize&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return True&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def download(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if len(self.item) &amp;gt; 4:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ##have to parse the page first &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.socket = urllib.urlopen(self.item.pageUrl)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; content = self.socket.read()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; pattern = self.item.regstr.rstrip()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; pattern = pattern.replace (&amp;#39;:&amp;#39;,&amp;#39;%3A&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; pattern = pattern.replace(&amp;#39;/&amp;#39;,&amp;#39;%2F&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; match = re.search(pattern,content)&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.item.url = match.group()[:]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  self.item.url = self.item.url.replace(&amp;#39;%3A&amp;#39;,&amp;#39;:&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.item.url = self.item.url.replace(&amp;#39;%2F&amp;#39;,&amp;#39;/&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Get url from page==&amp;gt;&amp;#39;,self.item.url &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; finally:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.socket.close()&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if not self.isNewSize(self.item.fileSize):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; print self.item.fileName, &amp;#39;==&amp;gt;Up to Date&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; path = &amp;#39;&amp;#39;.join(( self.item.filePath,&amp;#39;/&amp;#39;,self.item.fileName))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Starting download file &amp;#39;,self.item.url&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; os.system(&amp;#39; &amp;#39;.join((&amp;#39;start curl -o&amp;#39;,path ,self.item.url)))&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f = open(&amp;#39;&amp;#39;.join(( self.item.filePath,&amp;#39;/&amp;#39;,self.item.fileName)), &amp;#39;wb&amp;#39;)&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; while True:&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; data = self.socket.read(8192)&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if not data:&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; break &lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f.write(data)&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; finally:&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.socket.close()&lt;br&gt;##&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f.close()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def run(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.download()&lt;br&gt;&lt;br&gt;if __name__ == &amp;#39;__main__&amp;#39;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; lists = []&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; threads = []&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;loading config file...&amp;#39;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if os.path.exists(&amp;#39;updater.dat&amp;#39;):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f = open(&amp;#39;updater.dat&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for line in f: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; args = line.split(&amp;#39;,&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; lists.append(UpdateItem(args))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; finally:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f.close()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;done&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Starting job...&amp;#39; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for item in lists:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; parse = UrlParse(item)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ##parse.download()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; threads.append(parse)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; parse.start()&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for t in threads:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; t.join ()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;All done, Press any key to quit&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f = open(&amp;#39;updater.dat&amp;#39;,&amp;#39;w&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for item in lists:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f.write(str(item))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; finally: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f.close()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; raw_input()&lt;br&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Please make a config file.&amp;#39;&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-3653821323743027052?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/3653821323743027052/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=3653821323743027052' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3653821323743027052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3653821323743027052'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python207-06.html' title='Python练习:在线更新工具2(07-06)'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-6810574266160327628</id><published>2007-07-06T10:14:00.001+08:00</published><updated>2007-07-06T10:14:33.378+08:00</updated><title type='text'>Python Cookbook 2.3 在文件中进行查找和替换</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;要在文件中替换字符串.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;字符串替换在字符串处理中非常常见,可以使用string对象的replace方法来解决.我们在本节要做的工作是从文件中获取信息并保存到文件中去:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; import os, sys&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;nargs = len(sys.argv)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;if not 3 &amp;lt;= nargs &amp;lt;= 5: &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;quot;usage: %s search_text replace_text [infile [outfile]]&amp;quot; % \&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; os.path.basename(sys.argv[0])&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;else:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stext = sys.argv[1] &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rtext = sys.argv[2]&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; input_file = sys.stdin&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; output_file = sys.stdout&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if nargs &amp;gt; 3:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; input_file = open(sys.argv[3])&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if nargs &amp;gt; 4:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output_file = open( sys.argv[4], &amp;#39;w&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for s in input_file:&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output_file.write( s.replace(stext, rtext))&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; output.close( )&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; input.close( )&lt;/span&gt; &lt;br&gt;&lt;br&gt;本节非常简单,我们也没有比较把简单的问题讲的很复杂是不是?这个脚本分析输入参数,获得要替换的字符串,然后分别从文件中读取(或者标准输入),用循环处理替换字符串,再写入文件中(或标准输出),最后关闭了两个文件.&lt;br&gt;如果我们的内存能够容纳两个文件的大小,我们完全可以一次处理替换操作,这样对于小于100M的文件是没有问题的:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;output_file.write(input_file.read( ).replace(stext, rtext)) &lt;/span&gt;&lt;br&gt;&lt;br&gt;这样可以更快捷的完成我们的需求.&lt;br&gt;&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-6810574266160327628?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/6810574266160327628/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=6810574266160327628' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6810574266160327628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/6810574266160327628'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-23.html' title='Python Cookbook 2.3 在文件中进行查找和替换'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-3045757851142856083</id><published>2007-07-05T09:52:00.001+08:00</published><updated>2007-07-05T09:52:51.932+08:00</updated><title type='text'>Python Cookbook 2.2 文件写操作</title><content type='html'>&lt;span style="font-weight: bold;"&gt;需求:&lt;/span&gt;&lt;br&gt;&lt;br&gt;要写文本或者二进制数据到一个文件里.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;讨论:&lt;/span&gt;&lt;br&gt;&lt;br&gt;这里有一个很简单的方法,一次写一个长字符串到文件中:&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;open(&amp;#39;thefile.txt&amp;#39;, &amp;#39;w&amp;#39;).write(all_the_text)&amp;nbsp; # text to a text file &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;open(&amp;#39;abinfile&amp;#39;, &amp;#39;wb&amp;#39;).write(all_the_data)&amp;nbsp;&amp;nbsp;&amp;nbsp; # data to a binary file&lt;/span&gt;&lt;br&gt;&lt;br&gt;然而,最好是绑定一个文件对象,这样你在操作完的时候可以关闭它,比如:&lt;br&gt;&lt;br&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;file_object = open(&amp;#39;thefile.txt&amp;#39;, &amp;#39;w&amp;#39;)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;file_object.write(all_the_text)&lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt; &lt;span style="color: rgb(204, 0, 0);"&gt;file_object.close( )&lt;/span&gt;&lt;br&gt;&lt;br&gt;很懂情况下,要写的数据不是一个字符串,而是一系列字符串,在这种情况下,可以使用writelines方法(和名字所表达的含义不同,它不仅仅支持文本字符串):&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;file_object.writelines(list_of_text_strings) &lt;/span&gt;&lt;br style="color: rgb(204, 0, 0);"&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;open(&amp;#39;abinfile&amp;#39;, &amp;#39;wb&amp;#39;).writelines(list_of_data_strings)&lt;/span&gt;&lt;br&gt;&lt;br&gt;调用writelines方法要比循环调用write方法或者将若干字符串拼接后调用write方法要快很多.&lt;br&gt; 创建一个文件对象用于写操作的时候,要给open方法传递第二个参数,&amp;#39;w&amp;#39;或者&amp;#39;wb&amp;#39;,和上一节相同,建议使用异常处理,因为写操作比读操作更需要关闭文件,否则会出现文件内容的丢失,因为只有close了,文件内容才能保证在硬盘上,而不是内存中.&lt;br&gt;一次写一部分数据到文件,比一次从文件读一部分数据更常见.你可以通过循环调用write或writelines来实现这个需求,数据每次添加到文件的末尾,最后你再调用close方法来关闭文件.如果数据都是准备好的 ,调用一次writelines要比循环调用write更快;如果数据是一次来一点,使用write方法比较好,而不是缓存到内存中(比如使用append方法),最后一次调用writelines.读操作和写操作是完全不同的,对于写操作,一次写一点比一次写一大块要更方便一些.&lt;br&gt;当你使用&amp;#39;w&amp;#39;或者&amp;#39;wb&amp;#39;参数打开文件时,文件原先的内容立刻消失了.即使你打开它后立刻关闭,数据依然不存在了.如果你希望写操作添加数据到原先的文件末尾 ,可以使用&amp;#39;a&amp;#39;或者&amp;#39;ab&amp;#39;参数,还有更多的允许同时读和写操作的参数如&amp;#39;r+b&amp;#39;,是高级参数中最常用的.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;相关说明:&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;write(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; write(str) -&amp;gt; None.&amp;nbsp; Write string str to file. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Note that due to buffering, flush() or close() may be needed before&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; the file on disk reflects the data written.&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;writelines(...)&lt;/span&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; writelines(sequence_of_strings) -&amp;gt; None.&amp;nbsp; Write the strings to the file. &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Note that newlines are not added.&amp;nbsp; The sequence can be any iterable object&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; producing strings. This is equivalent to calling write() for each string.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38514629-3045757851142856083?l=tinylee.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tinylee.blogspot.com/feeds/3045757851142856083/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38514629&amp;postID=3045757851142856083' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3045757851142856083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38514629/posts/default/3045757851142856083'/><link rel='alternate' type='text/html' href='http://tinylee.blogspot.com/2007/07/python-cookbook-22.html' title='Python Cookbook 2.2 文件写操作'/><author><name>tinylee</name><uri>http://www.blogger.com/profile/02540041536319954174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38514629.post-899754892841774646</id><published>2007-07-04T11:44:00.001+08:00</published><updated>2007-07-04T11:44:30.262+08:00</updated><title type='text'>Python练习:在线更新工具(07-04)</title><content type='html'>每天学习一点Python Cookbook,总觉得不练习还是不能掌握要领,于是想写一个小工具:&lt;br&gt;1.能根据配置文件,在线更新需要的工具&lt;br&gt;2.很多绿色软件没有提供在线更新功能(如SciTe,还有卡巴的病毒库),而只是给出了更新的地址&lt;br&gt;3.更新地址有的是固定的(如卡巴的病毒库,360等),也有是不固定的(连接地址总是体现为文件名的变化)&lt;br&gt;&lt;br&gt;首先实现最简单的功能:&lt;br&gt;1.读写配置文件&lt;br&gt;2.下载有固定地址的文件 ,判断是否更新的依据是文件的大小,也就是html头中的Content-Length字段&lt;br&gt;3.对于变化地址的文件,分析其下载页面,找出需要的地址,如对于PyScripter,下载页面为&lt;a href="http://pyscripter.googlepages.com/,"&gt;http://pyscripter.googlepages.com/,&lt;/a&gt;而更新的地址可以写成:&lt;a href="http://pyscripter.googlecode.com/files/PyScripterv.+zip,"&gt; http://pyscripter.googlecode.com/files/PyScripterv.+zip,&lt;/a&gt;使用了简单的正则式.&lt;br&gt;&lt;br&gt;对于配置文件,先定义一下它的格式:&lt;br&gt;本地文件名,文件大小,保存目录,下载地址,下载页地址,正则式字符串&lt;br&gt;......&lt;br&gt;使用逗号分割字段,以后好处理,对于有固定地址的文件,可以没有后两项.&lt;br&gt;&lt;br&gt;为了方便处理,定义一个简单的数据结构:&lt;br&gt;class UpdateItem: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test.zip,20,c:\temp,&lt;a href="http://www.xxx.com"&gt;http://www.xxx.com&lt;/a&gt;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self,sequence):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.fileName = sequence[0]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.fileSize  = int(sequence[1])&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.filePath = sequence[2]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.url = sequence[3]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.len = 4&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if len(sequence) &amp;gt; 4:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.pageUrl = sequence[4]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.regstr  = sequence[5]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.len = 6&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __str__(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; str1 = &amp;#39;,&amp;#39;.join((self.fileName,str(self.fileSize),self.filePath,self.url))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if self.len != 4:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; str1 = &amp;#39;,&amp;#39;.join((str1, self.pageUrl,self.regstr))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return str1&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __len__(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return self.len&lt;br&gt;&lt;br&gt;其中的变量保存配置文件中对应的字段,构造函数中传递的sequnce列表是为了方便代码的书写.&lt;br&gt;__len__方法是为了日后判断是否有后两个字段用的.&lt;br&gt;__str__方法是为了以后写配置文件时方便,直接用str(item)就可以了. &lt;br&gt;还是用java的思路来写Python代码,所以看起来比较怪,哈哈.&lt;br&gt;&lt;br&gt;关于读配置文件,我决定首先要求用写一个简单的配置文件,否则程序进行不下去啊:&lt;br&gt;&lt;br&gt;if __name__ == &amp;#39;__main__&amp;#39;:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;&amp;#39;&amp;#39;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; lists = []&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if os.path.exists(&amp;#39;updater.dat &amp;#39;):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f = open(&amp;#39;updater.dat&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for line in f:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; args = line.split(&amp;#39;,&amp;#39;)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; lists.append(UpdateItem(args))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; finally:&lt;br&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f.close()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &amp;#39;Make a config file first!&amp;#39;&lt;br&gt;&lt;br&gt;这里为了方便,我们定义配置文件叫updater.dat了,用一个列表保存所有需要下载的项.&lt;br&gt;&lt;br&gt;关于写配置文件,当下载完成后,需要更新数据,可以这样写:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f = open(&amp;#39;updater.dat&amp;#39;,&amp;#39;w&amp;#39;) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for item in lists:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f.write(str(item))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; finally:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; f.close()&lt;br&gt;这就用到了UpdateItem的__str__方法了.&lt;br&gt;&lt;br&gt;下面就是程序的关键了部分:下载,首先是主程序的接口:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for item in lists: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; parse = UrlParse(item)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; parse.download()&lt;br&gt;&lt;br&gt;我们定义一个类,UrlParse,接收下载配置项,然后提供分析和下载的功能:&lt;br&gt;&lt;br&gt;class UrlParse:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self, item):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.item = item&lt;br&gt;里面保留一个item对象,方便以后处理. &lt;br&gt;&lt;br&gt;在下载以前,首先要判断是否需要更新,仅仅判断html头部就可以了:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def isNewSize(self, oldsize):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.socket = urllib.urlopen(self.item.url)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; fileSize = int(self.socket.headers[&amp;#39;Content-Length&amp;#39;])&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if oldsize == fileSize: &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return False&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.item.fileSize = fileSize&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return True&lt;br&gt;&lt;br&gt;如果文件大小发生了变化,就认为需要更新(算法太简单,不过应该能适用于大多数情况)&lt;br&gt;下面是下载函数了,它首先要判读是否要先分析出下载地址:&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def download(self):&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if len( self.item) &amp;gt; 4:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ##have to parse the page first&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; self.socket = urllib.urlopen(self.item.pageUrl)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; content = self.socket.read()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; pattern =  self.item.regstr&lt;br&gt;&a
