本节介绍常用的模块和函数

sys

包含一些与解释器关系紧密的变量和函数

  • argv:传递到解释器的命令行参数,包括脚本名称
  • exit([arg]):退出当前程序(如果在try/finally块中调用,finally子句仍会执行)
    • 可选参数arg:给定的返回值(通常用0表示成功)或错误信息
  • modules:映射模块名字到载入模块的字典
  • path:查找模块所在目录的目录名列表
  • platform:类似sunos5或win32的平台标识符
  • stdin:标准输入流——一个类文件(file-like)对象
  • stdout:标准输出流——一个类文件对象
  • stderr:标准错误留——一个类文件对象
In [1]:
#argv变量的使用——反序打印命令行参数
In [2]:
import sys
In [3]:
args = sys.argv[1:]       
#此处跳过了第一个元素,那是脚本的名字
#这里对sys.argv进行了复制,当然我们也可以在原始列表上操作,但是不安全 
In [4]:
args.reverse()      #反序排列,不返回值
In [6]:
print ' '.join(args)       #因为是用ipython notebook打开,会有很多参数
--parent=1 /home/zk/.ipython/profile_default --profile-dir --IPKernelApp.parent_appname='ipython-notebook' /home/zk/.ipython/profile_default/security/kernel-24117013-540c-46fe-b513-2b15243e7304.json -f

os

提供了访问多个操作系统服务的功能
os和它的子模块os.path还包括一些检查、构造、删除目录和文件的函数,以及一些处理路径的函数

  • environ:对环境变量进行映射
  • system(command):在子shell中执行操作系统命令
    • 在Windows中,还有特有的函数os.startfile用来打开窗口文件而不是DOS窗口
      由os.system或os.startfile启动外部程序后,python仍在运行
    • 在UNIX中,python会终止,直到命令执行完成
  • sep:路径中的分隔符
    • UINX是单斜杠“/”
    • Windows是双反斜杠“\\”
    • Mac OS是冒号“:”
    • 有些平台上,os.altsep包含可选的路径分隔符
      • Windows是单斜杠“/”
      • UNIX似乎没有可选的分隔符???
  • pathsep:分隔多个路径的分隔符
    • UNIX是冒号“:”
    • Windows是分号“;”
    • Mac OS是双冒号“::”
  • linesep:文本字符串的行分隔符
    • UNIX是单换行符“\n”
    • Windows是回车符+换行符"\r\n"
    • Mac OS是单回车符“\r”
  • urandom(n):返回n字节的加密强随机数据(“真”随机数)
    如果平台不支持,会产生NotImplementedError异常
In [1]:
#environ映射可以访问环境变量,也可以更改(但不是所有系统都能支持)
In [2]:
import os
In [5]:
#查看LANG环境变量
os.environ['LANG']
Out[5]:
'zh_CN.UTF-8'
In [6]:
#sep是当前系统的路径名分隔符
os.sep
Out[6]:
'/'
In [8]:
#UNIX好像没有可选的分隔符????
os.altsep
In [9]:
#pathsep是当前系统的多个路径名的分隔符
os.pathsep
Out[9]:
':'

fileinput

用于遍历文本文件的所有行

  • input([files [, inplace [, backup] ]):遍历多个输入流的行
    • 返回能够用于for循环遍历的对象
    • 默认(不带参数)查找需要循环遍历的文件
    • files参数:指定一个或多个文件名,放入文件序列依次访问
    • inplace参数:(布尔值)是否进行原地处理
      对于要访问的没一行,需要打印出替代的内容,以返回到当前的输入文件中
    • backup参数:(当inplace=True时,可选该参数):将文件名扩展备份到通过原始文件创建的备份文件中
  • filename():返回当前正在处理的文件名(包括当前正在处理的文本行的文件)
  • lineno():返回当前行的行数 这是一个累计值,完成一个文件的处理并开始处理下一个文件时并不会重置
  • filelineno():返回当前文件的当前行数
    非累计值,处理另一个文件时会被重置
  • isfirstline():返回布尔值,检查当前行是否为文件首行
  • isstdin():返回布尔值,检查最后一行是否来自sys.stdin
  • nextfile():关闭当前文件,移动到下一个文件
    跳过的行不计入lineno()
  • close():关闭序列(整个文件链),结束迭代
In [10]:
#fileinput使用——为python脚本添加行号(在行末作为注释)
In [11]:
import fileinput
In [20]:
for line in fileinput.input('/home/zk/桌面/chap10 自带电池/hello2.py',inplace=True):         #inplace为真,文本内容可修改
    line = line.rstrip()                #rstrip方法删除字符串末尾的指定字符(默认为空格)并返回结果
    num = fileinput.lineno()
    print '%-40s # %2i' % (line, num)
In [21]:
#inplace参数的使用很容易破坏程序,要十分小心

集合、堆、双端队列

集合(sets模块,无需手动导入)

Set类位于sets模块中,一般不需要创建Set类的实例,除非为了兼容python2.3以前的版本
集合是由序列或者其他可迭代对象构建的,主要用于成员资格检查,副本会被忽略(集合的互异性)

  • 并集:union方法、运算符“|”
  • 交集:intersection方法、运算符“&”
  • 判断是否为子集:issubset方法、运算符“<=”
  • 判断是否为超集:issuperset方法、运算符“>=”
  • 补集:difference方法、运算符“-”
  • 对称差:symmetric_difference方法、运算符“^”
  • 复制:copy方法
  • 添加元素:(原位操作)add方法
  • 删除元素:(原位操作)remove方法
In [22]:
#集合的互异性
set([0,0,0,0,0,0,0,1,1,1,1,2,3,])
Out[22]:
{0, 1, 2, 3}
In [22]:
 
In [23]:
a = set([1,2,3])
In [24]:
b = set([2,3,4])
In [25]:
#求并集——union方法
a.union(b)
Out[25]:
{1, 2, 3, 4}
In [26]:
#求并集——按位或(OR)运算符“|”
a | b
Out[26]:
{1, 2, 3, 4}
In [27]:
#求交集
a & b
Out[27]:
{2, 3}
In [28]:
c = a & b       #c是a和b的交集
In [29]:
#判断c是否为a的子集——issubset方法
c.issubset(a)
Out[29]:
True
In [30]:
#判断c是否为a的子集——运算符“<=”
c <= a
Out[30]:
True
In [31]:
#判断c是否为a的超集——issuperset
c.issuperset(a)
Out[31]:
False
In [32]:
#判断c是否为a的超集——运算符“>=”
c >= a
Out[32]:
False
In [34]:
#求交集——intersection方法
a.intersection(b)
Out[34]:
{2, 3}
In [35]:
#求交集——按位与(AND)运算符“&”
a & b
Out[35]:
{2, 3}
In [36]:
#求b关于a的补集(属于a而不属于b)——difference方法
a.difference(b)
Out[36]:
{1}
In [37]:
#求b关于a的补集(属于a而不属于b)——运算符“-”
a -b
Out[37]:
{1}
In [38]:
#求对称差(两个集合中不共有的所有元素)——symmetric_difference方法
a.symmetric_difference(b)
Out[38]:
{1, 4}
In [39]:
#求对称差(两个集合中不共有的所有元素)——运算符“^”
a ^ b
Out[39]:
{1, 4}
In [40]:
#复制集合——copy方法
a.copy()
Out[40]:
{1, 2, 3}
In [41]:
a.copy() is a
Out[41]:
False
In [42]:
a
Out[42]:
{1, 2, 3}
In [43]:
#添加元素——(原位操作)add方法
a.add(4)
In [44]:
a
Out[44]:
{1, 2, 3, 4}
In [45]:
#删除元素——(原位操作)remove方法
a.remove(4)
In [46]:
a
Out[46]:
{1, 2, 3}

集合(set)是可变(不可作为字典的键)、可散列的,不能包含其他集合
但是有一个frozenset类型,是不可变、可散列的集合

In [47]:
#set不能包含其他set
a.add(b)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-47-b2a6299f5117> in <module>()
      1 #set不能包含其他set
----> 2 a.add(b)

TypeError: unhashable type: 'set'
In [48]:
#但是set可以包含frozenset
a.add( frozenset(b) )
In [49]:
a
Out[49]:
{1, 2, 3, frozenset({2, 3, 4})}

堆——heqpq模块

heap为堆,q是queue的缩写即队列
优先队列的一种
使用优先队列能够以任意顺序添加对象,并且能在任何时间找到最小的元素
python没有独立的堆类型,但是有一些堆操作的函数

  • heappush(heap, x):将x入堆
    只能用于通过各种堆函数建立的列表中
    堆中的元素看似随意排列的,但是他们的顺序很重要
    堆的元素排列的顺序规则:位与i位置上的元素总比i////2位置处的元素大
    这是底层堆算法的基础,该特性称为堆属性(heap property)
  • heappop(heap):将堆中最小的元素弹出
    一般会弹出索引为0的元素,并且将剩余元素中的最小值移动到索引为0的位置上
  • heapify(heap):将heap属性强制应用到任意一个列表
    将一个一般的列表按照规则调整为堆
  • heapreplace(heap, x):将堆中的最小元素弹出,同时将x入堆
    效率比heappop + heappush高
  • nlargest(n, iter):返回iter中第n大的元素
  • nsmllst(n, iter):返回iter中第n小的元素

nlargest函数和nsmallst函数的操作其实可以用分片和排序来完成
但是使用堆算法效率更高,又更易用

In [51]:
from heapq import *
In [52]:
#heappush函数使用
In [53]:
from random import shuffle
In [54]:
heap = []      #先创建一个空列表,供堆函数操作
In [56]:
data = range(10)
In [57]:
shuffle(data)      #使按顺序排列的列表乱序(原位操作)
In [58]:
for n in data:  
    heappush(heap, n)
In [59]:
heap      #看起来是一个普通的列表,但是它有特定的排序规则,是一个堆
Out[59]:
[0, 1, 4, 2, 3, 5, 9, 8, 7, 6]
In [60]:
#heappop函数的使用
heappop(heap)
Out[60]:
0
In [61]:
heap     #部分元素的位置进行了调整
Out[61]:
[1, 2, 4, 6, 3, 5, 9, 8, 7]
In [62]:
#heapify函数的使用 
In [66]:
data      #一个普通的列表
Out[66]:
[5, 7, 1, 2, 6, 4, 9, 8, 0, 3]
In [67]:
heapify(data)           #将data列表调整为堆
In [68]:
data            #元素顺序按照堆的规则发生了改变
Out[68]:
[0, 2, 1, 5, 3, 4, 9, 8, 7, 6]

双端队列(double-ended queue,deque)

用于需要按照元素添加的顺序移除的情况
相关模块——collections模块,包含deque类型(通过列表等可迭代对象创建)
是一种特殊的列表,元素的弹出pop可以指定方向,而且元素可以左移或者右移,溢出的元素自动补充到另一端(相当于环形队列)

  • pop方法:弹出右端第一个元素
  • popleft方法:弹出左端第一个元素
  • append方法:在右端补充一个元素
  • appendleft方法:在左端补充一个元素
  • rotate(n)方法:队列向右移动n步
In [1]:
from collections import deque
In [2]:
q = deque([1,2,3,4,5])          #利用deque把列表转换为双端队列
In [3]:
q.append(6)
In [4]:
q.appendleft(0)
In [5]:
q
Out[5]:
deque([0, 1, 2, 3, 4, 5, 6])
In [6]:
q.pop()
Out[6]:
6
In [7]:
q.popleft()
Out[7]:
0
In [8]:
q
Out[8]:
deque([1, 2, 3, 4, 5])
In [9]:
q.rotate(3)       #队列右移三步
In [10]:
q
Out[10]:
deque([3, 4, 5, 1, 2])
In [14]:
q.rotate(-3)          #队列左移三步
In [15]:
q
Out[15]:
deque([1, 2, 3, 4, 5])
In [16]:
#extendleft方法类似,此处省略

time

与日期时间有关的模块
日期表示方法有三种

  1. 从“新纪元”的一月一日0点至今经历的秒数
    新纪元由平台决定,对于UNIX来说,是1970年
  2. 包含九个元素的元组,如:(2008, 1, 21, 12, 2, 59, 0, 21, 0)
    • 前六个元素分别是年月日时分秒,秒的范围是0~61秒,为的是应付闰秒和双闰秒
    • 第七个元素是周,范围0~6分别表示周一~周日
    • 第八个元素是儒历日,范围1~366
    • 第九个元素是夏令时,1表示真,0表示假,-1表示又程序自行判断能使mktime函数工作正常
  3. 包含五个字段的字符串,如Fri Dec 21 05:41:27 2008
    分别是星期、月、日、时间、年
  • asctime([tuple]):将时间元组转换为字符串(不带参数表示显示当前时间)
  • localtime([secs]):将“新纪元”至今秒数转换为时间元组(不带参数表示本地时间)
  • gmtime():与不带参数的localtime类似,不过显示的是全球统一时间
  • mktime(tuple):将时间元组转换为“新纪元”至今秒数,参数不可缺省
  • sleep(secs):休眠secs秒
  • strptime(string [, format]):将字符串转换为时间元组(与asctime相反),可以指定格式format,默认采用第三种日期显示形式
  • time():当前时间(“新纪元”至今秒数),全球统一时间
In [18]:
import time
In [19]:
#以字符串格式显示当前时间 
time.asctime()
Out[19]:
'Fri Mar  6 15:09:03 2015'
In [22]:
#以元组形式显示当前时间
time.localtime()
Out[22]:
time.struct_time(tm_year=2015, tm_mon=3, tm_mday=6, tm_hour=15, tm_min=13, tm_sec=48, tm_wday=4, tm_yday=65, tm_isdst=0)
In [33]:
#如果要以元组形式显示当前的全球统一时间
time.gmtime()
Out[33]:
time.struct_time(tm_year=2015, tm_mon=3, tm_mday=6, tm_hour=7, tm_min=22, tm_sec=6, tm_wday=4, tm_yday=65, tm_isdst=0)
In [25]:
#将元组形式转换为“新纪元“至今秒数
time.mktime(time.localtime())
Out[25]:
1425626127.0
In [27]:
#如果想以”新纪元“至今秒数的形式显示当前时间(和上面等价)
time.time()
Out[27]:
1425626283.627512
In [28]:
#休眠若干秒
time.sleep(2)
In [31]:
#将时间字符串转换为元组
time.strptime('Fri Mar  6 15:09:03 2015')
Out[31]:
time.struct_time(tm_year=2015, tm_mon=3, tm_mday=6, tm_hour=15, tm_min=9, tm_sec=3, tm_wday=4, tm_yday=65, tm_isdst=-1)

此外,python还支持datetim和timeit两个时间模块
前者支持日期和时间的算法
后者帮助开发人员对代码段的执行时间进行计时

random

包含返回随机值的函数,用于模拟或者用于任何产生随机输出的程序
产生的是伪随机数,可以满足一般的需要,但不适合用于加密
加密可以采用强随机数,更加接近真正随机数,如os.urandom函数和random.SystemRandom类

  • random():返回"0<n<=1"的随机实数n
  • getrandbits(n):以长整型的形式返回n个随机位(可用于加密等事务)
  • uniform(a, b):返回"a<=n<b"的随机实数n
  • randrange([start], stop, [step]):返回range(start, stop, step)列表的随机数
  • choice(seq):从序列seq中返回随机元素
  • shuffle(seq[, random]):(原位操作)将序列seq的元素顺序随机打乱
  • sample(seq, n):从seq中选择n个随机且互异的元素
In [38]:
import random
In [34]:
#例子:随机打牌
In [44]:
values = range(1,11) + "J Q K".split()     #创建牌面大小列表
In [45]:
suits = 'diamons clubs hearts spades'.split()     #创建牌面花色列表
In [46]:
deck = ['%s of %s' % (v, s) for v in values for s in suits]           #创建牌面列表,一整副牌,除了大小王
In [47]:
random.shuffle(deck)              #打乱这副牌
In [48]:
#牌数太多,假设只剩5张牌
del deck[5:]
In [49]:
print deck
['2 of diamons', 'J of hearts', '6 of hearts', 'J of diamons', 'K of hearts']

In [50]:
#随机(已乱序)打牌,直到打完
while deck:
    print deck.pop()
K of hearts
J of diamons
6 of hearts
J of hearts
2 of diamons

shelve

简单的文件存储方案

  1. 通过open函数打开文件并得到一个Shelf对象
  2. 将这个对象作为普通字典操作来存储数据(键必须是字符串)
  3. 完成工作后调用对象的close方法
    这个方案在查找元素时会新建一个副本,如果直接对这个副本赋值,是不能添加数据的
    这个方案的数据修改是即时写入磁盘的
In [51]:
import shelve
In [52]:
#潜在的陷阱
In [53]:
s = shelve.open('test.dat')
In [54]:
s['x'] = ['a', 'b', 'c']       #给字典添加一个列表数据
In [55]:
s['x'].append('d')        #企图给字典中的一个列表添加数据
In [56]:
s['x']      #失败了
Out[56]:
['a', 'b', 'c']
In [57]:
#解决方法一,通过绑定到这个副本上的临时变量
In [58]:
temp = s['x']
In [59]:
temp.append('d')
In [61]:
s['x'] = temp      #把修改了的副本赋回来
In [62]:
s['x']
Out[62]:
['a', 'b', 'c', 'd']
In [63]:
#解决方法二,借助open函数的wrtieback参数
#开启这个参数后数据的修改是异步写入的,直到close这个对象才把修改写入磁盘
In [64]:
s.close()     #先关闭原来的对象
In [65]:
s = shelve.open('test.dat', writeback = True)          #打开writeback
In [66]:
s['x']
Out[66]:
['a', 'b', 'c', 'd']
In [67]:
s['x'].append('e')
In [68]:
s['x']
Out[68]:
['a', 'b', 'c', 'd', 'e']
In [69]:
s.close()       #要记得关闭这个对象,才能把修改写入磁盘

其他标准模块

  • functools:能够通过部分参数来使用某个函数(部分求值),稍后再为剩下的参数提供值
  • difflib:计算两个序列的相似度;从一些序列中找出与某个序列最相似的一个
  • hashlib:通过字符串计算小“签名”(数字),可应用于大文本文件或用于加密等安全性用途
  • csv:读写CSV文件
    CSV是逗号分隔值(Comma-Separated Values)的简写,很多程序可以用来存储表格式数据的简单格式。主要用于不同程序间交换数据。
  • timeit:衡量代码片段运行时间的工具
  • profile:可用于代码片段效率的全面分析
  • trace:提供代码片段的总分析,告诉哪部分执行了,哪部分没有执行
  • datetime:支持特殊日期和时间对象,以多种方式对它们进行构建和联合,比time更加直观
  • itertools:创建和联合迭代器
  • logging:管理一个或多个核心的日至文件,同时对日志信息提供了多层次的优先级
  • getopt、optparse:处理命令行程序所使用的选项(option)或者开关(switches)
  • cmd:编写命令行解释器
In []: