看完了《Core Python 2nd》,入门是肯定了,但离掌握还有不小的距离。抛开那些数不尽的模块不说,单是语言这一块,仍然有不少特性只是了解,仍不能熟练地运用。用Stroustrup的话说:必须用语言的本质特征来编写程序 。我仍然有30%左右的地方在用C++的方式在写Python程序。所以在看《Python2.1 宝典》之际,我决定小记一下,起到熟练的作用,做一个Pythoner。

1.dict.get('thy', None) —— 没有'thy'时返回默认值

2.coerce(5.5, 2L) —— 把两个数字转换成为公共类型

3.divmod(5,2) —— 商和余数

4.s=''; name = s or 'index.html' —— 空串''可以等价于None

5.xrange —— 迭代中改进性能

6.[x*x for x in xrange(1,11)]
  [x*x for x in xrange(1,11) if x%2 == 0]
  [a+b for a in 'abc' for b in '123']
  [(x,ord(x)) for x in 'abc']

7.>>>[1,2]+[5]+['thy']
  [1,2,5,'thy']

8.>>>z=['a','b']
  >>>z*=2
  >>>z
  ['a','b','a','b']

9.>>>(1,2)+(3,4)
  (1,2,3,4)
 
10.filter(function, list) 
  >>>filter(lambda d:not d.isdigit(), 'P6yth12on') #返回对应真值的
  'Python'

  >>>filter(None, [12, 0, 'ehy', [], '', [1,2]]) #清除0、空值
  [12, 'ehy', [1,2]]

11.map(function, list[,list,...]) 
  >>>s=['thy', 'jlj']
  >>>map(string,capitalize, s)
  ['Thy', 'Jlj']

  >>>s=[1,2,3]; t=[5,6,7]
  >>>map(operator.mul, s, t)
  [5, 12, 21]

12.reduce(function, seq[,init]) 
  >>>reduce(operator.mul, [2,3,4])
  24 #=((2*3)*4)

  >>>reduce(lambda x,y: y+x+y, 'Hello', '-') #第一参数为init
  'olleH-Hello'

13.zip(seq[,seq,...])
  >>>zip([1,2,3],[4,5,6])
  [(1,4),(2,5),(3,6)]

  >>>zip((1,2,3))
  [(1,),(2,),(3,)]

14.
  >>>todo=['a','b','c','d']
  >>>todo[1:3]=['nap']
  >>>todo
  ['a','nap','d']
  >>>del z[1:3]
  >>>todo
  ['a']

15.
  >>>todo=['a']
  >>>todo.extend(['c','d'])
  >>>todo
  ['a','c','d']

16.
  >>>todo=['a','c','d']
  >>>todo.index('c')
  1
  >>>todo.index('e')
  ValueError: list.index(x): x not in list

17.
  >>>todo=['a','c','d','c']
  >>>todo.count('c')
  2

18.hash(obj)
  >>>hash(10)
  10
  >>>hash(10.0)
  10
  >>>hash((1,2,3))
  -821448277
  >>>hash([1,2,3])
  TypeError: unhashable type: 'list'

19.
  >>>z={'a':'xtt', 'b':'jlj'}
  >>>y={'a':'thy'}
  >>>z.update(y)
  >>>z
  {'a':'thy',
   'b':'jlj'}

20.
  >>>z={'a':'xtt', 'b':'jlj'}
  >>>z.items()
  [('a','xtt'), ('b','jlj')]
  >>>z.popitem() #任一键值
  ('b', 'jlj')

21.字典的浅拷贝
  >>>z={'a':'xtt', 'b':'jlj'}
  >>>y=z.copy() #浅拷贝
  >>>y
  z={'a':'xtt', 'b':'jlj'}

22.
  >>>s=['a','b','c']
  >>>id(s)
  73463048
  >>>t=s
  >>>id(s)
  73463048
  >>>t is s
  True
  >>>t=['a','b','c']
  >>>t is s
  False
  >>>t == s
  True

23.浅拷贝
  >>>s=['a','b',['c',1]]
  >>>import copy
  >>>t=copy.copy(s) #只创建容器本身的副本,对容器所包含的对象创建引用
  >>>t is s, t == s
  (False, True)
  >>> t[1]='c'
  >>> t
  ['a', 'c', ['c', 1]]
  >>> s[-1][0] = 2
  >>> t
  ['a', 'c', [2, 1]]

24.深拷贝
  >>>s=['a','b',['c',1]]
  >>>import copy
  >>>t=copy.deepcopy(s) #迭代创建容器的副本
  >>> s[-1][0] = 2
  >>> t
  ['a', 'c', ['c', 1]]

25.使用数组
  >>>import array #数据类型是确定的,所以比list性能高
  >>>z=array.array('b') #byte类型的数组
  >>>z.append(5)
  >>>z[0]
  5
  >>>q=array.array('i', [5,10,-3]) #int类型的数组,后面是初始数据(iterable)
  >>>
  >>>q
  array('i', [5,10,-3])

  #c - char
  #b - byte
  #h - short
  #i - int
  #L - long
  #f - float
  #d - double

26.高序与低序互换
  >>>import array
  >>>q=array.array('i', [1,2,3])
  >>>q.buffer_info() #低级信息
  (60061448, 3)
  >>>q.byteswap() #高序与低序互换
  >>>q
  array('i', [16777216, 33554432, 50331648])
  >>>q.byteswap() #高序与低序互换
  >>>q
  array('i', [1, 2, 3])

27.except ExceptionType, ArgumentVariable
try: file=open('SecretOptions.txt') except IOError, (ErrorNumber, ErrorString): pass else: #若try中的代码未引起异常 ParseOptionsFile(file)

28.作者极力建议用“异常事件”,否则应该做一些额外处理:

try: DoDangerousStuff() except: (ErrorType, ErrorValue, ErrorTB)=sys.exc_info() print sys.exc_info() traceback.print_exc(ErrorTB)

29.raise ExceptionType, ArgumentVariable
  >>>raise ValueError, 'Must be even'

30.finally
try: DataLock.acquire() expect RuntimeError, (ErrorNumber, ErrorString): pass finally: #无论try块是否产生异常事件都必须执行 DataLock.release()

30.assert Expression, ArgumentExpression
def KelvinToFahrenheit(Temperature): '''表达式为假,则会产生一个AssertionError ArgumentExpression会被当做AssertionError的参量''' assert (Temperature>=0), 'Colder than absolute zero!'
采用-O或者-OO命令行参量运行Python就会关闭断言。

31.函数对它的参量默认值只计算一次。作者建议避免使用动态、可变的默认值:
def PrintTime(TimeStamp=time.time()): print TimeStamp

PrintTime()
PrintTime() #将会打印与上次相同的时间

应该改为:
def PrintTime(TimeStamp=None): if TimeStamp==None: TimeStamp=time.time() print TimeStamp

32.任意参量
def func(*args, **kwargs): for arg in args: print arg for Name,Val in kwargs.items(): print Name, Val

func((1,2))  #未解包,Python会自动包装,即args=((1,2),)
func(*(1,2)) #解包,args=(1,2)
func(*(1,2), **{'a':1, 'b':2}) #解包,kwargs={'a':1, 'b':2}

33.reload强制再导入模块

34.global ValName可以避免Python搜索局部名字空间(*作者推荐使用)

35.compile(CodeString, FileName, Kind) #生成代码对象
   #FileName —— 文件名或者''
   #Kind —— exec:编译一个模块,single:编译一条语句,eval:编译一个表达式
   exec ExecuteObject [in GlobalDict[, LocalDict]]
   eval(ExpressionObject [,GlobalDict[, LocalDict]])

36.双下划线前缀可使旁观者不能直接查看这些属性。

37.isinstance(object, class)
   issubclass(sub, father)

38.weakref 弱引用
  >>> class A(object):
  ...     pass
  ...
  >>> a = A()
  >>> sys.getrefcount(a)
  2
  >>> b=a #强引用
  >>> sys.getrefcount(b)
  3       #因为强引用而增加了1
  >>> r = weakref.ref(a) #弱引用
  >>> sys.getrefcount(a)
  3       #弱引用并未增加其引用计数
  >>> r() #调用弱引用来检索引用的对象
  <__main__.A object at 0x04570A90>
  >>> sys.getrefcount(a)
  4
  因此弱引用不会引起垃圾回收。

  (thy——)弱引用的两个用途:
  ①为创建代价很高的对象(如socket对象)建立高速缓存
import weakref from socket import * socketCache = {} def getSocket(addr): if socketCache.has_key(addr): sock = socketCache[addr]() #若socket对象尚未被撤消,则调用之,使其成为强引用 if sock: return sock #否则 sock = socket(AF_INET, SOCK_STREAM) sock.connect(addr) #创建代价很高 socketCache[addr] = weakref.ref(sock) #保存弱引用 return sock #如果不采用弱引用,则必须一直保存socket对象。但由于socket对象的生命周期很长 #导致map中的socket对象一直得不到清除(因为以强引用保存在map中),除非手动去 #从map中移除,但socket对象何时能够结束很难追踪。从而大量的socket对象资源被白白消耗 #而使用了弱引用则会在socket对象不再使用时自动被回收,因为map中的是弱引用,不参与 #引用计数。

  ②解决循环引用的问题(A引用B,B又引用A):
import weakref class A: def __init__(self): print 'A.__init__' self.b = None def __del__(self): print 'A.__del__' class B: def __init__(self): print 'B.__init__' self.a = None def __del__(self): print 'B.__del__' if __name__ == '__main__': a = A() b = B() a.b = weakref.proxy(b) b.a = a

39.stdout的softspace属性决定是否需要在打印的下一项之前输出一个空格。
  >>>import sys
  >>>def joinEm(a,b):
  ...    print a,
  ...    sys.stdout.softspace = 0
  ...    print break

  >>>joinEm('Thanks', 'giving')
  Thanksgiving

40.输出重定向
  >>>print >> sys.stderr , 'File not found‘
  File not found
  >>>sys.stdout = open('fakeout.txt', 'wt')
  >>>print "Now who's going to do?"
  >>>sys.stdout.close()
  >>>sys.stdout = sys.__stdout__

41.类似文件的对象
  >>>class Reverse(object):
  >>>    def write(self, s):
  ...        s = list(s)
  ...        s.reverse()
  ...        sys.__stdout__.write(''.join(s))
  ...        sys.__stdout__.flush()

  >>>sys.stdout = Reverse()
  >>>print 'thyu'
  uyht

42.在交互模式下,‘_’为最后一次运行的结果值。
  >>> 4*2
  8
  >>> _
  8

43.translate(table[,deletestr])
  >>>Name='power smart report now?'
  >>>Name.title().translate(string.makestrans('?!', '!?'), string.whitespace)
  PowerSmartReportNow!

44.splitlines([keepends])
  >>>'The\r\nEnd\n\n'.splitlines()
  ['The', 'End', '']
  >>> 'The\r\nEnd\n\n'.splitlines(True)
  ['The\r\n', 'End\n', '\n']

45.(?P...)命名组,可以用(?P=name)再次匹配它
  #下面的reg只与开头和结尾都具有相同字母的单词匹配
  ^(?P\w)\w*(?P=letter)$

46.re.escape(str)将所有str中的正则元字符转义
  >>> re.escape('s\w')
  's\\\\w'

47.StringIO模块,将字符串当作文件处理(实际上是字符串缓冲,内存文件)
   可以用于在不必做很多小连接的情况下建立长字符串(否则每连接一次都会生成一个临时对象)
  >>> import StringIO
  >>> output = StringIO.StringIO()
  >>> output.write('Hello thy')
  >>> print >>output, 'haha'
  >>> output.getvalue()
  'Hello thyhaha\n'
  >>> output.close()

48.codecs.open(filename, mode[, encoding[, errors[, buffering]]])
   可以打开非ASCII码文件(open函数只能打开ASCII文件)
  >>> bob = codecs.open('test-uni.txt', 'w', 'utf-8')
  >>> bob.write(u'你好,田宏宇')
  >>> bob.close()
  >>> f = open('test-uni.txt')
  >>> for i in f:
  ...     print i
  ...   
  浣犲ソ锛岀敯瀹忓畤
  >>> f.close()
  >>> bob = codecs.open('test-uni.txt', 'r', 'utf-8')
  >>> for i in bob:
  ...     print i
  ...
  你好,田宏宇
  >>> bob.close()
   #从单字节到多字节叫做decoding,从多字节到单字节叫做encoding。
   #经常用到的是UTF-8和GB2312两种

49.codecs.EncodedFile(file, input[, output[, errors]])
   将open打开的文件对象翻译包装
  >>> f = open('test-uni.txt')
  >>> bob = codecs.EncodedFile(f, 'unicode-escape', 'utf-8')
  >>> for i in bob: print i
  ...
  \u4f60\u597d\uff0c\u7530\u5b8f\u5b87
  >>> f.close()

50.unicodedata模块可检查所有Unicode 5.1.0字符的属性。

51.os.access逐点测试属性
  >>> os.access('/usr/local', os.R_OK | os.X_OK)
  False
  >>> os.path.exists('c:/windows') # 等价于os.access('c:/windows', os.F_OK)
  True

52.os.chmod(path, mode)
   以所有者和组的方式处理文件许可权

53.os.path.isabs(path)
   是否为绝对路径

54.os.path.getatime(path)、os.path.getmtime(path)、os.path.getctime(path)
   最后一次访问时间、修改时间、创建时间
  >>> time.ctime(os.path.getatime('c:/windows/notepad.exe'))
  'Sun Oct 02 03:23:29 1994'

55.os.utime(path, (atime, mtime))
   如果(atime, mtime)为None,则设置为当前时间

56.os.stat(path) —— I-want-it-all方法
  >>> os.stat('/usr')
  posix.stat_result(st_mode=16877, st_ino=1454L, st_dev=64768L, st_nlink=13, st_uid=0, st_gid=0, st_size=4096L, st_atime=1260063788, st_mtime=1253714419, st_ctime=1253714419)
   其中st_mode是路径的模式值,可用stat模块的其它函数来测试
  >>> import stat
  >>> mode = os.stat('/usr')[stat.ST_MODE]
  >>> stat.S_ISDIR(mode)
  True
   对于unix,还有os.lstat(path)用于得到符号链接的信息

57.os.path.join(path1[, path2[, ...]])
   将目录联系接成为当前OS的有效路径
   os.path.split(path)、os.path.splitdrive(path)、os.path.splitext(path)、os.path.splitunc(path)
   切分路径与文件、盘符与路径、路径与后缀名、加载点与文件
   os.path.dirname(path)、os.path.basename(path)
   简化形式

58.os.listdir(path)
   列出所有文件(包含目录)
  
59.os.path.commonprefix(list)
   返回所有项共有的最长前缀

60.fnmatch模块,测试文件名的特殊模式
  >>> fnmatch.fnmatch('python', 'p*n')
  True

61.glob模块,以特殊模式搜索
  >>> for file in glob.glob('e:/voa*/*.mp[3,4]'):
  ...     print file
  e:/VOA Special English\025 Ski Jumping.mp3
  e:/VOA Stand English\Have a Heart.mp3
  e:/VOA Special English\Hepburn, 1907-2003.mp3

62.复制文件可以用os和shutil模块
   (thy——)shutil速度较慢,在win32下可以用win32file.CopyFile
   shutil.copyfile(src, dest)、shutil.copy(src, dest)、
   shutil.copy2(src, dest)、shutil.copyfileobj(src, dest[,buflen])
   shutil.copymode(src, dest)、shutil.copytree(src, dest[,symlinks])

63.unix下,os.symlink(src, dest)会创建一企业对src的符号链接
           os.link(src, dest)会创建一企业对src的硬链接

64.os.rmdir(path)、os.removedirs(path)
   删除、递归删除空目录
   *shutil.rmtree(path[, ignore_errors[, onerror]])
   递归删除所有,ignore_errors为True的话则不提示错误
   *用此函数要当心

65.tempfile模块返回临时文件对象
   tempfile.TemporaryFile([mode='w+b'[, bufsize=-1[, suffix=''[, prefix='tmp'[, dir=None]]]]])
   当file被close的时候会自动删除
   tempfile.mkstemp([suffix=''[, prefix='tmp'[, dir=None[, text=False]]]])
   file的使用者有义务删除它


66.filecmp模块:比较文件和目录
   difflib模块:比较文件(性能更优)

67.os.pipe()管道机制
  >>> r,w = os.pipe()
  >>> os.write(w, 'Pipe')
  4
  >>> os.read(r, 100)
  'Pipe'

68.class mmap.mmap(fileno, length[, tagname[, access[, offset]]])
   内存映射文件,像是字符串与文件的混合体(速度更快)

69.os.startfile(path[, operation])
   os.exec*(path, arg0, arg1, ...)
   exec系列函数将替换当前进程,而startfile不会

70.os.popen(command[, mode[, bufsize]])
   打开管道,以便与子进程通信,mode默认为r
  >>> a=os.popen('dir /w /ad e:\\')
  >>> print a.read()
  #返回一个准备好的文件对象

   os.popen2(command[, mode[, bufsize]])
   返回(stdin, stdout)
  >>> w,r = os.popen('grep ":"')
  >>> w.write(someText)
  >>> w.close()
  >>> print r.read()

  os.popen3(command[, mode[, bufsize]])
   返回(stdin, stdout, stderr)

  os.popen4(command[, mode[, bufsize]])
   返回(stdin, stdout+stderr)

71.os.spawn*(mode, path, ...)
  >>> os.spawnl(os.P_NOWAIT, 'd:\\python26\\python', 'python')
  400 #返回不替换当前进程的子进程的进程号

72.os.startfile(path[, operation])
   从此路径打开文件

73.os._exit(n)
   会跳过正常的清除操作,通常仅仅用于fork的子进程。
   sys.exit([status])
   更常用的方法,它会抛出SystemExit异常(也可以手动抛出)。
  >>> sys.exit('usage: zapper [-force]')
  usage: zapper [-force]

  C:\>

74.atexit模块
  >>> import atexit
  >>> def bye(msg):
  ...     print msg
  >>> atexit.register(bye, "I'm melting!")
  >>> raise SystemExit
  I'm melting!

75.ConfigParser模块
   读写配置文件(但最好用XML替代)

76.os.OSError类
   包含了三个属性:errno、strerror、filename
  >>> try:
  ...     os.close(-1)
  ... except OSError, e:
  ...     print 'OH! %s [err: #%d, fname: %s]' % (e.strerror, e.errno, e.filename)
  ...
  OH! Bad file descriptor [err: #9, fname: None]

  os.strerror(code)方法可以查到errno对应的文本信息
  errno模块包含每个错误代码的文本消息以及errorcode词典

77.signal模块
   处理异步信号
#此例程只能在Unix下运行 import signal import sys import time def handler(signum, frame): raise 'timeout: %d %d' % (signum, frame) # 注册信号处理函数 signal.signal(signal.SIGALRM, handle) #2秒后发送SIGALRM信号 signal.alarm(5) try: print 'Your name:' name = raw_input('Please enter') if name.strip() == 'thy': break print 'Sorry...' except: print "Too late!"

78.pickle模块、cPickle模块
   转换成与平台无关的字节表示法
import pickle class Point(object): def __init__(self, x, y): self.x, self.y = x, y def __str__(self): return '(%d, %d)' % (self.x, self.y) def __getstate__(self): '''保存实例对象时被pickle调用''' print 'Get state called.' return (self.x, self.y) def __setstate__(self, state): '''加载实例对象时被pickle调用''' print 'Set state called.' self.x, self.y = state def hello(self): print 'Hello:%s' % self.__str__() p = Point(10, 20) z = pickle.dumps(p) #load, dump是从到文件中 newp = pickle.loads(z) print newp newp.hello()
   要想load时调用对象的__init__,则应该实现object.__getinitargs__()

79.copy_reg模块
   可以为C扩展模块中的数据类型添加转换格式支持
   copy_reg.pickle(type, function[, constructor])

80.shelve模块(类似于dbm模块)
   把Python对象保存到待久的、类似数据库的存储器中
   把数据库看做词典进行访问数据
  >>> db = shelve.open('thy') #不可使用后缀名
  >>> db['secretCombination'] = [5,12,34]
  >>> db['account'] = 4564343
  >>> db.keys()
  ['account', 'secretCombination']
  >>> db.close()
   可以存储pickle能够存储的任意对象

81.示例:通过网络移动对象
#swap.py from socket import * import cPickle,threading ADDR = '127.0.0.1' # '127.0.0.1' = localhost PORT = 50000 bConnected = False def send(obj): '''Sends an object to a remote listener''' if bConnected: conn.send(cPickle.dumps(obj,1)) else: print 'Not connected!' def listenThread(): '''Receives objects from remote side''' global bServer, conn, obj, bConnected while True: # Try to be the server. s = socket(AF_INET,SOCK_STREAM) try: s.bind((ADDR,PORT)) s.listen(1) bServer = True conn = s.accept()[0] except Exception, e: # Probably already in use, so I'm the client. bServer = False conn = socket(AF_INET,SOCK_STREAM) conn.connect((ADDR,PORT)) # Now just accept objects forever. bConnected = True while 1: o = conn.recv(8192) if not o: break; obj = cPickle.loads(o) print 'Received new object' print obj bConnected = False # Start up listen thread. threading.Thread(target=listenThread).start() print 'Listen thread started.' print 'Use swap.send(obj) to send an object' print 'Look in swap.obj to see a received object'
   开启两个Python进程,注意:python -i -c "import swap"
   -c 表示执行import swap命令,即仅仅执行导入
   -i 在执行命令之后让Python保持运行
***************进程1*******************
D:\Projects\Python\Trivial>python -i -c "import swap"
Listen thread started.
Use swap.send(obj) to send an object
Look in swap.obj to see a received object
>>> swap.send(['er',2,3])
>>> Received new object
[2, 3]
>>> swap.obj
[2, 3]
***************进程2*******************
D:\Projects\Python\Trivial>python -i -c "import swap"
Listen thread started.
Use swap.send(obj) to send an object
Look in swap.obj to see a received object
>>> Received new object
['er', 2, 3]
>>> swap.obj
['er', 2, 3]
>>> swap.send([2,3])

82.struct模块
   在Python对象与C结构之间转换
  >>> z=struct.pack('iic', 10,20,'z') #默认为高序优先
   可以创建一个C结构的等价物:
   struct {
       int a;
       int b;
       char a;
   }
  反之:
  >>> struct.unpack('i i c', z) #可以加空格
  (10, 20, 'z')
  >>> struct.unpack('2ic', z) #与上面相同
  (10, 20, 'z')
  >>> x=struct.pack('!iic', 10,20,'z') #加!可更改为低序优先

   struct模块读写二进制文件很有用,比如WAV文件的开头为:
   'RIFF' (4 bytes)
   little-endian length field (4 bytes)
   'WAVE' (4 bytes)
   'fmt'  (4 bytes)
   format subchunk length (4 bytes)
   format specifier (2 bytes)
   number of channels (2 bytes)
   sample rate in Hertz (4 bytes)
   bytes per second (4 bytes)
   bytes per sample (2 bytes)
   bits per channel (2 bytes)

  >>> s=open(r'c:/windows/media/ringout.wav', 'rb').read(36)
  >>> struct.unpack('<4si4s4sihhiihh', s)
  ('RIFF', 88228, 'WAVE', 'fmt ', 16, 1, 2, 44100, 176400, 4, 16)

83.文件压缩模块zlib、gzip、zipfile、zipimport、bz2、tarfile
   zlib对数据对象进行压缩,压缩格式与gzip兼容
   gzip使读写.gz文件如同读写普通文件
  >>> f = gzip.open('e:/thy.gz', 'wb')
  >>> f.write('''Oh my god!
  ... I just want a job!''')
  >>> f.close() #会在E盘下面生成thy.gz,内中有e:\thy
   zipfile允许读、写zip文件以及获得文件信息,其中有ZipFile,ZipInfo和PyZipFile类
   ①zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])
  >>> z=zipfile.ZipFile('e:/Matlab_CUDA-1.1a.zip')
  >>> z.printdir()
  File Name                                             Modified             Size
  Matlab_CUDA_1.1/bin/                           2007-11-20 17:49:24            0
  Matlab_CUDA_1.1/bin/nvmex.pl                   2007-06-06 16:50:00       106606
  Matlab_CUDA_1.1/fft2_cuda.c                    2007-11-20 13:49:40         5885
  >>> z.close()
   ②zipfile.ZipInfo([filename[, date_time]])
   ③zipfile.PyZipFile只有一个方法PyZipFile.writepy(pathname[, basename])
     用于创建包含Python模块和包的Zip文件。

84.time.clock() 返回秒数(常用于相减计时)
   time.strftime(format[, t]) 格式化字符时间
   time.strptime(string[, format]) 解析时间

85.calendar模块,用来访问日历
  >>> calendar.monthcalendar(2009, 12)
  [[0, 1, 2, 3, 4, 5, 6],
   [7, 8, 9, 10, 11, 12, 13],
   [14, 15, 16, 17, 18, 19, 20],
   [21, 22, 23, 24, 25, 26, 27],
   [28, 29, 30, 31, 0, 0, 0]]
   其中每一行是一个星期。
  >>> print calendar.month(2009, 12, 3, 2)
         December 2009
 
  Mon Tue Wed Thu Fri Sat Sun
 
        1   2   3   4   5   6

    7   8   9  10  11  12  13

   14  15  16  17  18  19  20

   21  22  23  24  25  26  27

   28  29  30  31

   #calendar.month(theyear, themonth[, width[, linesPerWeek]])
   calendar.weekday(year, month, day) 返回周一0~周日6
   calendar.monthrange(year, month) 返回在year年中month月的第一天的周日以及月份的长度
   calendar.isleap(year) 是否闰年

86.anydbm模块
   基于磁盘的词典格式(简单的数据库)
  >>> simpleDB = anydbm.open('e:/thy', 'c')
  >>> simpleDB['thy'] = 'goodguy'
  >>> simpleDB.keys()
  ['thy']
  >>> simpleDB.close()
   anydbm模块会从其它(n)dbm中选择最佳模块,而这些模块是互不兼容的,
   因此需要whichdb模块来确认anydbm创建了哪个版本
  >>> z=anydbm.open('e:/thy', 'c')
  >>> z.close()
  >>> import whichdb
  >>> whichdb.whichdb('e:/thy')
  'dbhash' #dbhash提供了键导航first()、last()、previous()、next()

87.sqlite3模块
   cur.description游标属性,包含7项tuple的序列。

88.socket模块
   一次典型的Socket连接:
   *侦听端(服务端)
  >>> s = socket(AF_INET,SOCK_STREAM)
  >>> s.bind(('127.0.0.1', 44444))
  >>> s.listen(1) #参数为传入接连的最大数
  >>> q,v = s.accept() #Socket q and address v
  >>> v
  ('127.0.0.1', 7489)
  >>> q.send('Hello from Python!')
  18
   *连接端(客户端)
  >>> s = socket(AF_INET,SOCK_STREAM)
  >>> s.connect(('127.0.0.1', 44444))
  >>> s.recv(1024)
  'Hello from Python!'

   如果需要确保数量庞大的数据全部已经发送出去,则需要对send的返回值进行校验:
def safeSend(sock, msg): sent = 0 while msg: i = sock.send(msg) if i == -1: return -1 sent += i msg = msg[i:] time.sleep(25) #等待队列清空 return sent

   send、recv用于面向连接的套接字,而sendto、recvfrom用于非面向连接的套接字
   另外在多播时使用recvfrom将可以知道是谁的消息
   socket.makefile([mode[, bufsize]]) 可以将Socket包装成类似文件的对象

   默认情况下,Socket会被阻塞,调用socket.setblocking(flag)可以改变这一行为,
   当Socket未阻塞时,若请求导致程序受阻,会发送error异常。这样可以让其它程序来
   决定是否继续请求。
s.setblocking(0) #不阻塞 while bKeepGoing: #由程序的其它部分来设置 try: q,v = s.accept() except error: q = None if q: price***equest(q,v) else: time.sleep(0.25)

   socket.ntohs(x)、socket.ntohl(x)、socket.htonl(x)、socket.htons(x)将
   (h)ost与(n)etwork的字节进行转换,包括(s)hort和(l)ong
   socket.inet_aton(ip_string)、socket.inet_ntoa(packed_ip)将IP地址与32bit二进制数字进行转换
   socket.setsockopt(level, optname, value) 设置Socket选项,如:
   s.setsockopt(SOL_IP, IP_ADD_MEMBERSHIP, inet_aton(addr)) #联接一个多播组
   s.setsockopt(SOL_IP, IP_DROP_MEMBERSHIP, inet_aton(addr)) #退出一个多播组
   s.setsockopt(SOL_IP, IP_MULTICAST_TTL, 2) #多播中包能够传送的最大转发器数,这样包不会太快被丢弃
   s.setsockopt(SOL_SOCKET, SO_REUSEADDR, True) #设置本场地址、端口重用,这样多个程序可以绑定同一个

89.SocketServer模块
   为Socket服务器类包装定义一个基类,包括TCPServer、UDPServer子类。
   典型的SocketServer用法:
  >>> import SocketServer
  >>> addr = ('127.0.0.1', 25)
  >>> server = SocketServer.ThreadingTCPServer(addr, MailRequestHandler) #后者为虚构
  >>> server.serve_forever()
   自定的Handler只要覆盖BaseRequestHandler的handle方法即可:
class EchoRequestHandler(SocketServer.BaseRequestHandler): def handle(self): while True: msg = self.request.recv(1024) if not msg: break print ' Received :' , msg print 'Done!' server = SocketServer.ThreadingTCPServer(('127.0.0.1', 25), EchoRequestHandler) server.handle_request() #之后即可在客户端用Socket连接发送消息
  
   若服务器设置为永远服务,则以上Handle可精简为:
class EchoRequestHandler(SocketServer.BaseRequestHandler): def handle(self): msg = self.request.recv(1024) print ' Received :' , msg server = SocketServer.ThreadingTCPServer(('127.0.0.1', 25), EchoRequestHandler) server.serve_forever()

90.一个最简单的支持CGI脚本的Web服务器
import SocketServer, CGIHTTPServer SocketServer.ThreadingTCPServer(('127.0.0.1', 80), \ CGIHTTPServer.CGIHTTPRequestHandler).serve_forever()
   这样可以打开http://127.0.0.1/hi.txt (hi.txt要在脚本所在的目录)

91.BaseHTTPRequestHandler、SimpleHTTPRequestHandler、CGIHTTPRequestHandler
   BaseHTTPRequestHandler是StreamRequestHandler的子类,接受一个HTTP连接、读和提取标题
   SimpleHTTPRequestHandler发送客户机请求的文件、目录
  >>>import webbrowser, threading, SimpleHTTPServer

  >>>def go():
  ...    t = SimpleHTTPServer.test #test会在8000端口上启动一个新的服务器
  ...    threading.Thread(target=t).start()
  ...    webbrowser.open('http://127.0.0.1:8000')

  >>>go()
   CGIHTTPRequestHandler继承SimpleHTTPRequestHandler,又添加了执行CGI脚本的支持。
   e:\web\test.htm、e:\web\cgi-bin\test.py
   ##e:\web\test.htm:


Your name:



##e:\web\cgi-bin\test.py import os print 'Content-type: test/html\r\n' #标题之后一定要输出一个空行\r\n name = os.environ.get('QUERY_STRING', '') #环境变量QUERY_STRING保存了向服务器提交的数据 print 'Hello, %s!

' % name[:] #这里name为'user=thy&sex=male' print '' #所有写入stdout的信息均会返回到客户机

   在e:\web上启动Python
  >>> import CGIHTTPServer
  >>> CGIHTTPServer.test()

92.select模块
   使得I/O密集程序不由线程切换等人工因素驱动,而是由I/O性能驱动。
   select.poll()返回一个轮询对象Polling Objects。
   poll.register(fd[, eventmask]) 注册与poll相关的文件描述符
   poll.poll([timeout]) 返回(fd, event)

93.asyncore模块
   由事件(如数据的到来)引起线程切换,而不是无用的切换。也相当于不使用线程

94.urllib库
urllib.urlcleanup()   #clean the cache
urllib.quote('human:my thy')   #进行%##编码
urllib.unquote('human%3Amy%20thy')   #进行%##解码

urllib.quote_plus('human:my thy')   #进行%##plus编码,并将值用+连接
urllib.unquote('human%3Amy+thy')   #进行%##解码

urllib.urlencode({'name':'thy', 'species':'sea bass'})   #将所给的字典进行%##plus编码

95.Internet协议
httplib、poplib、smtplib、ftplib

96.处理Internet数据
urlparse解析url地址:
>>> urlparse.urlparse('http://www.google.com/search?q=sexby&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:zh-CN:official&client=firefox-a')
ParseResult(scheme='http', netloc='www.google.com', path='/search', params='', query='q=sexby&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:zh-CN:official&client=firefox-a', fragment='')

urljoin合并基准url和新的url,对于锚点很有用:
>>> urlparse.urljoin('http://www.google.com/search/thy/index.htm', '../../foo.htm')
'http://www.google.com/foo.htm'

97.robotparser模块
分析web根目录的robots.txt文件。
roboBuddy = robotparser.RobotFileParser()
urlTuple = urlparse.urlparse(url)
robotURL='http://'+URLTuple[1]+'/robots.txt'
roboBuddy.set_url(robotTRL)
roboBuddy.read()

98.webbrowser模块
在Web浏览器中查看文件。可以用register方法用特定的浏览器打开url
>>> webbrowser.register('firefox', webbrowser.Mozilla)
>>> ff = webbrowser.get('firefox')
>>> ff.open('www.google.cn')

99.rfc822模块
分析EMail

100.base64模块
用ASCII来编码/解码二进制数据。

101.cookie模块
cookie.SimpleCookie将Cookie名称映射为Cookie值。
Cookie.Morsel保存键/值对。

102.处理XML
DOM:提前读取整个XML到内存中,比较简单,但不适用于巨大的XML文件
     xml.dom
SAX:Simple API for XML,事件驱动型,xml.sax

103.curses模块
(Linux下的)文本模式用户界面管理器。
import curses
main = curses.initscr()
main.addstr('hello thy', curses.A_UNDERLINE | curses.A_BOLD)
main.getch()
curses.endwin()

104.shlex和cmd模块
提供简单的命令解释程序

105.winsound模块
在Windows平台播放声音
winsound.PlaySound(sound, flags) 播放WAV文件

106.sndhdr模块
测试音频文件的格式

107.aifc、wave、sunau模块
分别处理AIFF、WAV、AU文件,界面几乎一样。

108.imghdr模块

识别图像文件格式

109.colorsys模块
在颜色系统RGB、YIQ、HLS、HSV之间进行转换

110.PIL——Python图像库
主要是Image模块
PIL模式值:
1 —— 1位像素,黑白
L —— 8位像素,黑白
P —— 8位像素,使用256位调色板
RGB —— 每像素3字节,真彩
RGBA —— 每像素3字节,带α通道的真彩
I —— 32位整型像素
F —— 32位浮点型像素

>>> import Image
>>> im = Image.open('d:/henry/pictures/001.jpg')
>>> im.mode
'RGB'
>>> im.size
(1024, 768)
>>> im.format
'JPEG'
>>> im.getbands()
('R', 'G', 'B')
>>> im.show()
>>> im.convert('1').show()
>>> im.save('001_pil.gif')

crop()裁剪、resize()、thumbnail()缩略图
getpixel()、putpixel()

ImageDraw模块,生成Draw对象,可以在图像上添加文字和形状。
>>> pts=[]    #接上面代码
>>> from random import randrange
>>> for i in range(10):
...     pts.append((randrange(im.size[0]),
                    randrange(im.size[1])))
...
>>> draw.line(pts)
>>> im.show()

其它功能见www.pythonware.com

111.预防死锁
在临界段之间放try...finally是很好的习惯
LogFileLock.acquire(1)
try:
    LogFileLock.write('some bytes')
finally:
    LogFileLock.release()

112.使用docstrings
pydoc模块,python pydoc.py -w urllib将生成的模块urllib的文档写入urllib.htm文件
doctest模块,使docstrings与代码同步

113.hotshot模块
由C写成,其中的Profile对象,可以做性能测试:
>>> import hotshot, hotshot.stats, test.pystone
>>> prof = hotshot.Profile("stones.prof")
>>> benchtime, stones = prof.runcall(test.pystone.pystones)
>>> prof.close()
>>> stats = hotshot.stats.load("stones.prof")
>>> stats.strip_dirs()
>>> stats.sort_stats('time', 'calls')
>>> stats.print_stats(20)
    850004 function calls in 10.090 CPU seconds

   Ordered by: internal time, call count

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    3.295    3.295   10.090   10.090 pystone.py:79(Proc0)
   150000    1.315    0.000    1.315    0.000 pystone.py:203(Proc7)
    50000    1.313    0.000    1.463    0.000 pystone.py:229(Func2)
# 调用次数 此函数总 此函数平均 累积时间 平时累积 文件名:行数(函数名)
# 累积时间为函数及子函数所花费的时间

!现在推荐用cProfile模块来代替hotshot,profile模块仅仅在需要扩展模块时才建议使用

114.排序优化技巧
对一列对象进行排序时,如果能找到排序的“关键”,即易于排序的数字、字符等等,当然应该基本是Unique的,可加快排序速度。
def SortByKey(list, keyMaker): tempList = map(lambda x,f=keyMaker:(f(x),x), list) tempList.sort() #对(a,b)中的a排序 return map(lambda(key,x):x, tempList) #扔掉(a,b)中的a

115.getpass模块
在命令行输入密码

116.rexec模块
在沙盒中运行Python代码

117.ast模块——Abstract Syntax Trees
抽象语法分析模块

118.数字签名
MD5模块
>>> import md5
>>> m = md5.new()
>>> m.update(data)
>>> m.digest()
>>> m.hexdigest()
SHA模块
>>> import sha
>>> s = sha.new()
>>> s.update(data)
>>> s.hexdigest()

119.C扩展Python
使用Py_INCREF(x)增加引用,Py_DECREF(x)减少引用

120.gmpy模块
任意精度整数算法库

121.traceback模块
处理栈记录
traceback.print_last()显示最后一次未捕获的异常
traceback.extract_stack()以元组列表形式返回异常
traceback.format_*()格式化异常

对于随意的Exception,也不要吞下异常,至少应该志记一下
try: DoSomething() except: traceback.print_exec()
122.pyclbr模块
不用导入模块而得到模块的有限信息

123.tokenize模块
将代码标记化并做语法分析

124.ast模块
抽象语法分析树

125.types模块
内置类型模块

126.dis模块
反汇编和检查pyc字节码
>>> f=lambda x:x*2
>>> import dis
>>> dis.dis(f)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (2)
              6 BINARY_MULTIPLY    
              7 RETURN_VALUE       

127.国际化
i18n代表Internationalization
比如hello.py文件中,
def _(s): return s print _('what do u want to do today?') print '1 -', _('Baking') print '2 -', _('Playing E-game!')

然后pygettext.py -d hello hello.py,会在hello.py所在的目录生成hello.pot(事先应该将path设置好),内容如下:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR , YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2010-03-20 11:50+China Standard Time\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"


#: D:\Projects\Python\Trivial\hello.py:3
msgid "what do u want to do today?"
msgstr "你今天想干什么"

#: D:\Projects\Python\Trivial\hello.py:4
msgid "Baking"
msgstr "烤"

#: D:\Projects\Python\Trivial\hello.py:5
msgid "Playing E-game!"
msgstr "电玩"


改动处为原来的charset=CHARSET改为charset=UTF-8
将hello.pot改名为hello.po,再msgfmt.py hello.po会生成hello.mo。
与hello.py平行地新建文件夹hello,内再新建文件夹LC_MESSAGES,将生成的hello.mo置于其中。

回到hello.py,将第一行改成:
import os, gettext #def _(s): return s os.environ['LANGUAGE'] = 'hello' _ = gettext.translation('hello', '.').lgettext

现在运行的结果为:
你今天想干什么
1 - 烤
2 - 电玩


128.imp模块 —— 探访import的内部机制
>>> import imp
>>> imp.find_module('urllib')
(Python26\Lib\urllib.py', mode 'U' at 0x0474ECA0>,
 'D:\\Programs\\Python26\\Lib\\urllib.py',
 ('.py', 'U', 1))
>>> imp.find_module('numpy')
(None, 'D:\\Programs\\Python26\\lib\\site-packages\\numpy', ('', '', 5))

——写在结束时:尽管这是一本介绍Python2.1的书,但其介绍的模块之全面,例程之丰富还是让我受益匪浅,而且介绍的模块中有80%左右仍然在Python2.6.5的标准库里在使用。时间关系有点虎头蛇尾,我还会回来 的!