2004年05月11日

sets是 Python 2.3 中新增的,它可以用来处理集合类型的数据。什么是集合?无序、唯一。


在这个模块中提供了两个集合类:Set(可变集合)和ImmurableSet(不可变集合)。


在我以前写过的一篇Blog中(一个Python小程序:目录比较程序(一) )有一段代码需要求两个目录中相同文件名的列表,我当时是将两个列表进行排序,然后通过一遍扫描进行求解,还是有一点算法的难度的。如果使用集合类就简单和清晰多了。代码如下:


import filecmp, sys, os
from os.path import walk, isfile, join, basename, normpath, splitext
import sets



if __name__ == “__main__”:
    dir1=normpath(sys.argv[1])
    dir2=normpath(sys.argv[2])
    len1=len(dir1)+1
    len2=len(dir2)+1
    files1=[]
    files2=[]
    exts=['.pyc', '.bak', '.ddd', '.png', '.gif', '.jpg']


    def visit(arg, dirname, names, files=files1, length=len1):
        if basename(dirname)!=’CVS’:
            files +=[join(dirname, file)[length:].replace(‘\\’, ‘/’)
                for file in names if isfile(join(dirname, file))
                and splitext(file)[1].lower() not in exts]


    walk(dir1, visit, 0)
1    dirs1 = sets.Set(files1)


    def visit(arg, dirname, names, files=files2, length=len2):
        if basename(dirname)!=’CVS’:
            files +=[join(dirname, file)[length:].replace(‘\\’, ‘/’)
                for file in names if isfile(join(dirname, file))
                and splitext(file)[1].lower() not in exts]


    walk(dir2, visit, 0)
2    dirs2 = sets.Set(files2)
   
3    common=dirs1 & dirs2
4    dirs1.difference_update(common)
5    dirs2.difference_update(common)
6    files1 = list(dirs1)
7    files1.sort()
8    files2 = list(dirs2)
9    files2.sort()
10    commons=list(common)
11    commons.sort()
   
12    match, mismatch, error=filecmp.cmpfiles(dir1, dir2, commons)


    print ‘%s vs %s’ % (dir1, dir2)
    print ’state filename’
    print ‘—– ——————————’
    for f in files1:
        print ‘  >   %s’ % f
    for f in files2:
        print ‘  <   %s’ % f
    for f in match:
        print ‘  =   %s’ % f
    for f in mismatch:
        print ‘ !=   %s’ % f


第1行:生成dirs1集合
第2行:生成dirs2集合
第3行:求dirs1和dirs2的交集,即求两个目录中相同文件名的集合
第4行:求只在dirs1中存在的文件名,带有_update的方法会更新原集合对象,而不带的则会生成新的集合
第5行:同第4行,求只在dirs2中存在的文件名
第6-7行:将集合转化为列表,并排序
第8-9行:同第6-7行
第10-11行:同第6-7行
第12行:比较两个目录中同名的文件


不过集合是无序的,因此当你需要按顺序输出元素时则需要先将其转化为有序的列表或元组,再进行输出。这一点有些麻烦。


生成一个列表可以从list或tuple甚至dictionary直接生成。如果直接使用dictionary,则会取出键值作为集合的元素,如:



>>> a={1:’a', 2:’b'}
>>> b=sets.Set(a)
>>> b
Set([1, 2])


如果想将字典的值生成集合怎么办呢?



>>> b=sets.Set(a.values())
>>> b
Set(['a', 'b'])


更详细的关于集合类的使用请查阅 Python 2.3 的文档。

作为实验性的 NewEdit 项目现在已经转移到 www.tigris.org 上去了,访问地址为:http://newedit.tigris.org 。上面已经有了可以运行的框架代码,欢迎大家下载交流。请记住,这是一个实验性项目,目前只具备一些基本的功能,随着它的发展,功能会越来越强,最终应可以应用于你的日常工作之中。


现在代码只可以通过 cvs 下载,不过从tigris.org上下载源代码比起sf.net上要容易得多了。下面是匿名用户下载代码的说明(详情可以参考项目主页上的cvs使用说明)。


检测源代码使用 CVS 客户端。例如:



cvs -d :pserver:anoncvs@cvs.tigris.org:/cvs login


需要输入口令时,直接敲入回车即可。


随后是



cvs -d :pserver:anoncvs@cvs.tigris.org:/cvs checkout newedit


 

2004年05月10日






file( filename[, mode[, bufsize]])


file()函数是2.2中新增的函数,它与open()函数一样,相当于open()的别名,不过比open()更直观一些。


读出一个文件的内容很简单:



text = file(filename).read()


这里我省略了模式(mode)参数,它缺省为’r'。


现在 Python 已经支持三种主要平台的回车符:’\n’是Unix的换行符、’r'是Macintosh的换行符、’\r\n’是Windows的换行符。那么在打开文件时使用’U'或’rU’模式就可以同时支持这三种换行符。


如果要对文件进行一行行的处理,有多种方法:



  • 先一次性将文本行读到一个列表中,再对列表进行处理


lines = file(filename).readlines()
for line in lines:
    print line



  • 使用文件对象的readline()方法进行一行行的处理


f = file(filename)
while True:
    line = f.readline()
    if line:
        print line
    else:
        break



  • 还有就是2.3中的新方法,在for循环中直接使用文件对象


for line in file(filename):
    print line


这是因为文件对象中增加了迭代功能。


注意:上面读出的每一行都带有回车符,因此在某些情况下你可能需要将它们去掉。

enumerate是python 2.3中新增的内置函数,它的英文说明为:









enumerate( iterable)

Return an enumerate object. iterable must be a sequence, an iterator, or some other object which supports iteration. The next() method of the iterator returned by enumerate() returns a tuple containing a count (from zero) and the corresponding value obtained from iterating over iterable. enumerate() is useful for obtaining an indexed series: (0, seq[0]), (1, seq[1]), (2, seq[2]), …. New in version 2.3.

它特别适合用于一个for循环时,当我们同时需要计数和元素时可以使用这个函数。举个简单的例子,有一个字符串数组,需要一行一行打印出来,同时每行前面加上计数,从1开始。



s = ['abc', 'This is a test', 'Hello, Python']
for i, line in enumerate(s):
    print i+1, line

2004年05月09日

今天把NewEdit放在了tigris.org上了,原来是在开源共创联盟上,但不知怎么地cvs用不了了,但我的帐户没有问题。也实在懒得去和cosoft去联系。还有一点就是,我对使用ssh有些讨厌,虽然我现在用它是一点问题都没有(使用cygwin),但每次都要输入口令,好麻烦。想到SubVersion是放在tigris.org上,于是就上去看了看,并申请到了一个帐号,不过现在项目还未经过审批。但就是未审批,我已经可以使用cvs上传我的源码了,真不错。而且它的cvs很简单,与我平时工作中用的一样。只要在cvs login时输入一次口令就可以了,以后就不用再很麻烦的输入口令了。大家有兴趣可以在上面创建自已的项目。


访问我的NewEdit项目可以去newedit.tigris.org。