模块是程序
下面是一个简单的模块导入过程,其中hello为预先编辑好的模块,放在桌面上
>>> import sys
>>> sys.path.append('C:\Users\hcs\Desktop')
>>> import hello
hello
>>> import hello
如上,同一个模块只装载一次,如果非要再装载一次可以使用reload(),在Python3.0中已经去掉了reload函数。尽管使用exec能实现同样的功能,但是应该尽可能避免重复载入模块。
>>> reload hello
SyntaxError: invalid syntax
>>> reload(hello)
hello word
<module 'hello' from 'C:\Users\hcs\Desktop\hello.py'>
>>> hello
<module 'hello' from 'C:\Users\hcs\Desktop\hello.py'>
>>> hello = reload(hello)
hello word
>>> hello
<module 'hello' from 'C:\Users\hcs\Desktop\hello.pyc'>
在UNIX系统中不能只是简单地将'/python'添加到sys.path中,必须使用完整的路径。(/home/username/python).如果想要此操作自动完成,可以使用sys.path.expanduser('/python')。
这里就是告诉解释器,处理默认目录外,还需要在append()指定的目录中查找模块。
导入模块后出现的.pyc文件是经过编译的、与平台无关的。
模块儿用于定义
模块的真正作用在于它们可以保持自己的作用域,这就意味着模块中定义的所有的类和函数以及赋值后的变量都成为了模块儿的特性。
在模块中定义函数:
如果希望模块可以像普通程序一样执行,可以对Python解释器使用-m切换开关来执行程序,例如存在program.py,可以通过如下命令执行:
python -m program args
程序就会执行带参数args的program程序。
在模块中增加测试代码:
将测试代码放在条件为:__name __ == '__main __'的if条件句中,如果需要编写完整的代码将其放在单独的程序中会更好。
让你的模块儿更有用
在前面的代码中通过改变sys.path来让解释器能够找到模块,但是理想的情况是:从一开始sys.path就是正确的路径,这可以通过两种方法实现。
1、将模块放置在正确的位置
这可以通过打印sys.path来找到正确的位置。
如果需要打印的数据结构内容过大,可以使用pprint模块中的pprint函数代替普通的print,它会提供更加智能的输出。
2、告诉解释器去哪里找
标准的实现方式是在PYTHONPATH环境变量中包含模块儿所在目录,PYTHONPATH会因操作系统不同而有所差异。
在UNIX或Mac中,可以在每次登陆都要执行的文件中设置环境变量。如果使用类似bash的shell文件,那么要设置的就是.bashrc,添加如下命令:
export PYTHONPATH=$PYTHONPATH:~/python(多个路径用:分割)
windows中的环境变量配置文件为:autoexec.bat,可以在C盘根目录下找到,添加如下代码:
set PYTHONPATH=%PYTHONPATH%;C\python
3、命名模块
包含模块儿代码的文件名字要和模块儿名一样,再加上.py扩展名,windows中也可以使用.pyw扩展名。
包
包基本是就是另外一类模块,有趣的是它能包含其他模块,当模块存储在文件中时,包就是其所在的目录,为了让Python将其作为包对待,它必须包含一个命名为init.py的文件。
探究模块
模块中有什么
1、使用dir
dir会将模块的所有特性以及模块中所有的函数、类、变量等列出。
如果喜欢用tab补全,则应该查看库参考中的readliner和lcompleter模块,它们在探究模块时很管用。
2、all变量
它定义了模块的公有接口,更准确地说,它告诉解释器:从模块导入所有名字代表什么含义
如果不使用all,用import* 语句默认将会导入模块儿中不以下划线开头的所有全局名称。
用help获取帮助
使用help与直接检查文档字符串相比,它的好处在于会获得更多的信息,比如函数签名(也就是所带的参数)
从本质来说,deepcopy(x)会将存储在x中的值作为属性进行复制,而copy(x)知识复试x,将x中的值绑定到副本的属性上。
文档
学习Python编程,最有用的莫过于Python库参考(http://python.org/doc/lib)
使用源代码
阅读源码是除自己编程外学习Python的最好方式。
查找代码位置可以通过sys.path,然后自己找源码,也可以通过以下代码:
print copy.__file__
来检查模块的__file __属性。
注意,有些模块并不包含任何可以阅读的Python源代码。他们可能已经融入到解释器内了(如:sys),或者是使用C语言写得。
标准库:一些最爱
sys
一些重要的函数和变量
函数/变量 | 描述 |
---|---|
argv | 命令行参数,包括脚本名称 |
exit([arg]) | 退出当前程序,可选参数为指定返回值或错误信息 |
modules | 映射模块名字到载入模块的字典 |
path | 查找模块所在目录的目录名列表 |
platform | 类似sunos5或win32的平台标识符 |
stdin | 标准输入流——一个类文件(file-like)对象 |
stdout | 标准输出流——一个类文件对象 |
stderr | 标准错误流——一个类文件对象 |
os
一些重要的函数和变量
函数/变量 | 描述 |
---|---|
environ | 对环境变量进行映射(访问或修改(不是所以系统都支持)某(PYTHONPATH)环境变量) |
system(command) | 在子shell中执行操作系统命令 |
sep | 路径中的分隔符 |
pathsep | 分割路径的分隔符 |
linesep | 行分隔符 |
urandom | 返回n个字节的加密强随机数据 |
os.system函数用于执行外部程序,还有其他一些函数,如:execv(),他会退出Python解释器,并且将控制权交给被执行的程序。还有popen(),它可以创建于程序连接的类文件。
subprocess是Python 2.4中新增的一个模块,它包括了os.system、execv和popen函数的功能
下面代码用于UNIX调用路径下的火狐浏览器:
os.system('/usr/bin/firefox')
下面代码用于windows下调用路径下的火狐浏览器:
os.system(r'c:\"Program Files"\"Mozilla Firefox"\firefox.exe')
windows中调用外部程序更好的方式为:
os.startfile(r'D:\Program Files\QQ\Bin\QQ.exe')
主义在Windows中,有os.system或os.startfile启动外部程序后,Python程序仍会继续运行,而在UNIX中,程序则会停止,等待os.system执行完。
对于启动浏览器访问某网址来说如下命令更方便:
>>> import webbrowser
>>> webbrowser.open('http://www.python.org')
True
fileinput
一些重要的函数和变量
函数/变量 | 描述 |
---|---|
input(files[, inplace[, backup]]) | 便于遍历多个输入流中的行 |
filename() | 返回当前文件名称 |
lineno() | 返回当前(累计)的行数 |
filelineno() | 返回当前文件的行数 |
isfirstline() | 检查当前行是否为文件中的第一行 |
isstdin() | 检查最后一行是否来自sys.stdin |
nextfile() | 关闭当前文件,移动到下一个文件 |
close() | 关闭序列 |
下面是一个例子:
import fileinput
for line in fileinput.input(inplace = 1):
line = line.rstrip()
num = fileinput.lineno()
print('%-40s # %2i' % (line, num))
执行命令:python numberlins.py numberlins.py(利用numberlins.py为自身代码编号),结果为
import fileinput # 1
for line in fileinput.input(inplace = 1): # 2
line = line.rstrip() # 3
num = fileinput.lineno() # 4
print('%-40s # %2i' % (line, num)) # 5
集合、堆、双端队列
1、集合
Python2.3中,集合通过set类型的实现成为了语言的一部分,所以不需要导入sets模块,可以通过set()直接定义集合
更多信息参考:http://python.org/doc/lib/types-set.html
>>> mySet = []
>>> for i in range(10):
mySet.append(set(range(i, i +5)))
>>> mySet
[set([0, 1, 2, 3, 4]), set([1, 2, 3, 4, 5]), set([2, 3, 4, 5, 6]), set([3, 4, 5, 6, 7]), set([8, 4, 5, 6, 7]), set([8, 9, 5, 6, 7]), set([8, 9, 10, 6, 7]), set([8, 9, 10, 11, 7]), set([8, 9, 10, 11, 12]), set([9, 10, 11, 12, 13])]
>>> mySet = reduce(set.union, mySet)
>>> mySet
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
>>>
上面的例子中调用了set模块的union方法的未绑定版本。
集合是可变的,所以它不能用作字典中的键。另外一个问你就是集合本身只能包含不可变(可散列)值,所以也就不能包含其他集合
为了更切实际(实际中集合的集合很常见),还有一个frozenset类型,用于代表不可变(可散列)的集合
2、堆
Python中的堆为小根堆
Python中并没有堆类型,只有一下包含堆操作函数的模块,即heapq(堆队列)
一些重要的函数
函数 | 描述 |
---|---|
heappush(heap, x) | 将x入堆 |
heappop(heap) | 将堆中的最小元素出堆 |
heapify(heap) | 将heap属性强制运用于任意列表 |
heapreplace(heap, x) | 将堆中的最小元素弹出,同时x入堆 |
nlargest(n,iter) | 返回iter中第n大的元素 |
nsmallest(n,iter) | 返回iter中第n小的元素 |
nlargest、nsmallest用来查找任意可迭代对象的n最大或n最小元素,之所以会出现在这是因为使用堆查找效率高。
3、双端队列
Python2.4增加了collections模块,它包括deque类型,Python2.5中的collections模块只包括deque类型和defaultdict类型(为不存在的键提供默认值的字典),未来可能会加入B-Tree和斐波那契堆
常见方法有:append、appendleft、pop、popleft、rotate、extend、extendleft
其中,extendleft中使用的可迭代对象会反序出现在双端队列中。
time
新纪元的1月1日点是一个与平台相关的年份,对UNIX来说是1970年
一些重要的函数
函数 | 描述 |
---|---|
asctime([tuple]) | 将时间元组转化为字符串 |
localtime([secs]) | 将秒数转化为日期元组,以本地时间为准 |
mktime(tuple) | 将时间元组转换为本地时间 |
sleep(secs) | 休眠secs秒 |
strptime(string[, format]) | 将字符串解析为时间元组 |
time() | 返回iter中第n小的元素 |
random
random模块所产生的数字都是伪随机,若想产生真正的随机数,应该使用os模块的urandom函数,random模块内的SystemRandom类也有类似功能,可以让数据接近真正的随机数。
有关全球统一时间的更多,请参考:http://en.wikipedia.org/wiki/Universal_time
一些重要的函数
函数 | 描述 |
---|---|
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中随机采样 |
shelve
如果只需要简单的存储方案,那么shelve模块可满足你的大部分的需要,你所要做的只是为它提供文件名。其唯一重要的的函数是open(文件名),在调用的时候会返回一个shelf对象,你可以用它来存储内容。只需把它当做普通的字典即可。
>>> import shelve
>>> import shelve as sh
>>> s = sh.open('test.dat')
>>> s
{}
>>> s['x'] = [1, 2, 3]
>>> s['x'].append(4)
>>> s['x']
[1, 2, 3]
>>> temp = s['x']
>>> temp.append(4)
>>> s['x'] = temp
>>> s['x']
[1, 2, 3, 4]
异常程序中如果不用temp作为变量保存s[‘x’],4就不会被存入s'x',使用temp可以解决这个问题,在Python2.4后还有一个解决方法:将open函数的参数writeback参数设置为true(适用于数据量不大的情况)。
re
除了标准文档外,Andrew Kuchling的“Regular Expression HOWTO”(http://amk.ca/python/howto/regex/)也是学习正则表达式的优秀资源。
1、什么是正则表达式
- 通配符
. 可以匹配除换行外的所有字符(只匹配一个) - 转义
r'python.org' - 字符集
使用中括号创建字符集如[a-zA-Z0-9]能匹配任意大小写的字母和数字(字符集只能匹配一个这样的字符)
[^abc]:反转字符集
字符集中的特殊字符
在字符集中对特殊字符转义一般是不需要的,但要记清下面规则
1、脱字符(^)出现在开头需要转义
2、中括号(])和横线(-)应该放在字符集的开头或者转义(横线可以放在末尾) - 选择符和子模式
如果想匹配‘Python’和‘Perl’可以写成:‘Python|Perl’或‘P(ython|erl)’ - 可选项和重复子模式
可选项(?)的例子:r'(http://)?(www\.)?python\.org'
还有以下符号:
1、(pattern)*:0次或多次
2、(pattern)+:1次或多次
3、(pattern){m,n}:m~n次 - 字符串的开始和结尾
之前的匹配都是匹配整个字符串
匹配开头:'^pattern'
匹配结尾:'pattern$'
有关正则表达式运算符的完整列表,请参见Python参考的4.2.1内容(http://python.org/doc/lib/re-syntax.html)
re模块的内容
一些重要的函数
函数 | 描述 |
---|---|
compile(pattern[, flags]) | 根据正则表达式的字符串创建模式对象 |
search(pattern, string[, flags]) | 在字符串中寻找模式 |
match(pattern, string[, flags]) | 在字符串开头匹配模式 |
split(pattern, string[, maxsplit]) | 根据模式的匹配项来分割字符串 |
findall(pattern, string) | 列出字符串中模式的所有匹配项 |
sub(pat, repl, string[, count=0]) | 将字符串中与pat匹配的模式用repl替换 |
escape(string) | 将字符串中所有特殊正则表达式字符转义 |
3、匹配对象和组
re中能够进行匹配的函数而言,他们会把找到的模式以MatchObject的形式返回
re匹配对象的重要方法
函数 | 描述 |
---|---|
group([group1, ……]) | 获取给定子模式的匹配项 |
start([group]) | 返回给定组匹配项的开始位置 |
end([group]) | 返回给定组匹配项的结束位置 |
span([group]) | 返回给定组匹配项的开始和结束位置 |
4、作为替换的组号和函数
见证re.sub强大功能的最简单的方式是在替换的字符串中使用组号
>>> import re
>>> emphasis_pattern = re.compile(r'''
\* #Beginning emphasis tag -- an asterisk
( #Begin group for capturing pharse
[^\*]+ #Capture anything except asterisks
) #end group
\* #ending emphasis tag
''', re.VERBOSE)
>>> re.sub(emphasis_pattern, r'<em>\1</em>', 'hello *world*')
'hello <em>world</em>'
让正则表达式变得更加易读的方式是在re函数中使用VERBOSE标志。
用函数作为替换内容可以让替换功能变得更加强大,MatchObject将作为函数的唯一参数,返回的字符串将被用作替换内容
贪婪和非贪婪模式
前面提到的重复运算符是是贪婪的(默认),意味着它会进行尽可能多的匹配
所有的重复运算符都可以通过在其后面加上一个问号变成非贪婪版本。
其他有趣的标准模块
- functools:包含一些可以使用部分参数的函数(部分求值),稍后再为剩下的参数提供数值。在Python3.0中,filter和reduce包含在该模块中。
- difflib:计算两个序列的相似度。还能从一些序列中找出和提供的序列最相似的那一个,可以用于创建简单的搜索程序。
- hashlib:通过字符串计算小“签名”,几乎可以确保为两个不同的字符串创建的签名不同,该模块可以运用于大文本文件,在加密和安全性方面有很多用途
- csv:CSV为Comma-Separated Values(逗号分隔值)的简写,很多程序都可以用它来存储表格式数据,主要用于在不同的程序间交换数据。使用csv模块可以轻松读取scv文件并处理。
- timeit、profile和trace:timeit模块(及命令行脚本)是衡量代码段运行时间的工具,可以代替time进行性能测试。profile(和伴随模块pstats)可用于代码段效率的全面分析。trace模块(和程序)可以提供总的分析,即哪部分执行了哪部分没执行。
- datetime:time模块不能满足时间追踪方面需求时,datetime模块就有用了,它支持特殊的日期时间对象,你可以对他们进行构建和联合。
- itertools:很多工具用来构建和联合迭代器(或其他可迭代对象),还包括扩展功能,如:链接可迭代对象、创建返回无限连续整数的迭代器。
- logging:让开发人员管理一个或多个日志文件,对日志信息提供了多层次的优先级。
- getopt、optparse:正确处理UNIX命令行不同的选项(开关),这两个模块是可行的解决方案。
- cmd:编写命令行解释器,也许可以将它作为程序的用户界面。