第十章 自带电池(模块)

python 自带的模块  标准库(standard library)

10.1.1    模块是程序

1.名字
2.位置
使用
>>> import sys
>>> sys.path.append('c:/python')
或者sys.path.expanduser()

首先,我们利用import语句 输入 sys模块。基本上,这句语句告诉Python,我们想要使用这个模块。sys模块包含了与Python解释器和它的环境有关的函数。

当Python执行import sys语句的时候,它在sys.path变量中所列目录中寻找sys.py模块。如果找到了这个文件,这个模块的主块中的语句将被运行,然后这个模块将能够被你 使用 。注意,初始化过程仅在我们 第一次 输入模块的时候进行。另外,“sys”是“system”的缩写。

我们可以观察到sys.path的第一个字符串是空的——这个空的字符串表示当前目录也是sys.path的一部分,这与PYTHONPATH环境变量是相同的。这意味着你可以直接输入位于当前目录的模块。否则,你得把你的模块放在sys.path所列的目录之一。

pyc文件

而Python语言写的程序不需要编译成二进制代码。你可以直接从源代码 运行 程序。在计算机内部,Python解释器把源代码转换成称为字节码的中间形式,然后再把它翻译成计算机使用的机器语言并运行。事实上,由于你不再需要担心如何编译程序,如何确保连接转载正确的库等等,所有这一切使得使用Python更加简单。由于你只需要把你的Python程序拷贝到另外一台计算机上,它就可以工作了,这也使得你的Python程序更加易于移植。
输入一个模块相对来说是一个比较费时的事情,所以Python做了一些技巧,以便使输入模块更加快一些。一种方法是创建 字节编译的文件 ,这些文件以.pyc作为扩展名。字节编译的文件与Python变换程序的中间状态有关(是否还记得Python如何工作的介绍?)。当你在下次从别的程序输入这个模块的时候,.pyc文件是十分有用的——它会快得多,因为一部分输入模块所需的处理已经完成了。另外,这些字节编译的文件也是与平台无关的。所以,现在你知道了那些.pyc文件事实上是什么了。
导入模块不意味这执行某些操作,主要是用于    定义    。所以,多次定义和单次定义是一样的
定义后,模块执行一次,对象都成了模块的特性

那么,为什么只导入一次呢?
如果有两个互相导入的模块,如果不是只导入一次,会进入死循环
如果非要重新载入模块
使用           reload()     返回重新载入的模块(3.0中不能用了
如果旧版本的类已经被实例化了,重载新版本类后,实例还是旧版本类的实例




如果想要让模块像程序一样运行?
使用         -m        切换开关
例如:progname.py模块导入后,运行python -m progname args  命令就会运行带命令行参数args的程序


10.1.2  模块的定义

1.在模块中定义函数
2.增加测试代码      __name__
通过告知模块本身是作为程序还是导入模块   工作
在主程序中  __name__的值为  “__main__” 
如果是导入模块               值为模块名字
#hello.py
def hello():
    print "hello world!"
def test():
    hello()
if __name__=='__main__':test()#如果是在主程序中运行,测试代码

10.1.3    让你的模块可用

1.把模块放对位置
2.设置位置
#pprint:更加智能的打印
①  编辑sys.path
②PYTHONPATH环境变量
  在用户变量中,修改PYTHONPATH  注意以分号间隔
或者编辑autoexec.bat文件,在C盘找到,编辑
如:set PYTHONPATH=%PYTHONPATH%:C:\python
也可以使用python的路径配置文件(.pth)来完成
3.模块命名:使用   .py   window也可以用   .pyw


10.1.4 包(package)

可以把模块打包,放到一个目录之下,这个目录就是“  包  ”(包目录)。把包作为   普通模块  导入的话,__init__.py文件(模块)的内容就是包的内容,内容可用,但是drawing 和colors 模块则不可用,导入后才能用

包里必须要有一个    __init__.py  文件(包代码)
假如有个包‘drawing’   ,目录下有'__init__.py'    'colors.py'   'shapes.py'   
就可以:
import drawing                #imports the drawing package
import drawing.colors         #imports the colors module
from drawing import shapes

10.2   探究模块

如何探究不认识的模块呢?
10.2.1模块中有什么?

1.使用 dir()
将对象的所有特性列出
2. __all__      变量
__all__在模块内部被设置,定义了模块的公有接口 (public interface) :告诉解释器,从模块导入所有名字代表什么含义,所以
使用  
from copy import *
那么,就你可以使用 __all__中包含的函数,如果想使用别的函数,就得显式的导入
模块设定时,如果没有设定 __all__,导入模块会导入所有不以下划线开头的全局名称

10.2.2    使用help

可以获得帮助
使用 __doc__  查看模块的文档字符串
help 与 __doc__相比,可以获得更多信息 :函数签名(所带参数)

10.2.3   文档 __doc__

查看文档字符串

10.2.3  查看源代码  __file__

找到模块的位置,去查看源代码




10.3 标准库

看书P20~29

1.sys模块 (完整的去看书)

访问与python解释器联系紧密的变量和函数
argv(命令行参数)
在用命令行调用python时,有时会在后面加入一些参数,这是用来传递参数的 sys.argv[0]是脚本的名字。
sys.stdin    
sys.stdout
sys.stderr       模块变量是类文件流对象(见11章)  可以使用read等。。。。

2.os模块

提供了访问多个操作系统服务的功能(具体看书)
system(command)   :用来执行外部程序,执行操作系统命令
比如
os.system(r'C:\"Program Files"\"Mozilla Firefox"\firefox.exe')
但是这问题很多
比如游览器打开后会访问 叫做 Files"\Moz.....的网站,或者shell 关闭后才打开游览器
总之,不好(其实把有空格的目录缩写,就没问题了)
注意:使用命令行时,如果路径有空格,极可能发生错误   重点!!!!!!!!!!!   在设置环境变量中也要注意
1.使用  双引号 “   ”
2.使用  八位字符 ~1
3.创建镜像
可以使用win的特有函数  os.startfile
os.startfile(r'C:\Program Files\Mozilla Firefox\firefox.exe')        
↑包含空格也没关系

对于启动特定任务,使用webbrowser模块是更好的选择
>>> import webbrowser
>>> webbrowser.open('www.baidu.com')

10.3.4  集合,堆 ,队列(数据结构)

1.集合(set)        
集合由序列(或其他可迭代对象)构建       本身也可迭代
集合可变,但本身只能包含不可变的值(即不能包含集合,但是可以使用frozenset类型来代表不可变集合),集合无序
1.用于检查成员资格,所以, 重复的成员会被忽略
2.用于集合操作
p181
2.堆(heap) 
二叉树中,父结点比左右孩子都大(小)
堆属性):i位置上的元素总比i/2上的大
python 中没有堆的类型,只有列表
只有一个包含堆操作函数的模块    heapq   (heap queue(队列,因为堆时优先队列的一种))

heappush()函数不能直接用于一般的列表。只能用于由堆函数创建的列表(就是必须用heappush把元素一个个输入空列表)。 因为元素的顺序很重要
heappop(heap):将堆中最小的元素弹出(一般是索引位置为0的元素)
heapify()   :把   堆属性    赋给任意列表  (强制付给,会自动把普通列表转换为合法的堆)
所以一般列表在试用 heappush前要试用 heapify

nlargest(n,iter):寻找可迭代对象iter中第n大(小)的元素
nsmallest(n,iter)
3.双端队列(double-ended queue)
在模块  collections 模块中    ,包含deque模块 (类型)
通过可迭代对象(列表  集合之类的)创建   使用append    appendleft等在其左右加入元素    rotate左右移动
>>> from collections import deque
>>> q=deque(range(5))
>>> q.append(5)
>>> q.appendleft(6)
>>> q
deque([6, 0, 1, 2, 3, 4, 5])
>>> q.pop()
5
>>> q.popleft()
6
>>> q.rotate(3)
>>> q
deque([2, 3, 4, 0, 1])
>>> q.rotate(-1)
>>> q
deque([3, 4, 0, 1, 2])





10.3.5 time  模块

时间元组

10.3.6   random 模块

返回随机数(伪随机数)  真随机要去试用os.urandom  或者random.SystemRandom

10.3.7   shelve模块(书架)pickle

shelve是一额简单的数据存储方案,他只有一个函数就是open(),这个函数接收一个参数就是文件名,然后返回一个shelf对象,你可以用他来存储东西,就可以简单的把他当作一个字典,当你存储完毕的时候,就调用close函数来关闭
这个有一个潜在的小问题,如下:
[python]  view plain  copy
  1. >>> import shelve  
  2. >>> s = shelve.open('test.dat')  
  3. >>> s['x'] = ['a''b''c']  
  4. >>> s['x'].append('d')  #这里读取的只是s['x']的一个拷贝
  5. >>> s['x']  
  6. ['a''b''c']  
存储的d到哪里去了呢?其实很简单,d没有写回,你把['a', 'b', 'c']存到了x,当你再次读取s['x']的时候,s['x']只是一个拷贝,而你没有将拷贝写回,所以当你再次读取s['x']的时候,它又从源中读取了一个拷贝,所以,你新修改的内容并不会出现在拷贝中,解决的办法就是,第一个是利用一个缓存的变量,如下所示
[python]  view plain  copy
  1. >>> temp = s['x']  
  2. >>> temp.append('d')  
  3. >>> s['x'] = temp  
  4. >>> s['x']  
  5. ['a''b''c''d']  
在python2.4中有了另外的方法,就是把open方法的writeback参数的值赋为True,这样的话,你open后所有的内容都将在内存cache中,当你close的时候,将全部一次性写到硬盘里面。如果数据量不是很大的时候,建议这么做。

下面是一个基于shelve的简单数据库的代码
[python]  view plain  copy
  1. #database.py  
  2. import sys, shelve  
  3.   
  4. def store_person(db):  
  5.     """ 
  6.     Query user for data and store it in the shelf object 
  7.     """  
  8.     pid = raw_input('Enter unique ID number: ')  
  9.     person = {}  
  10.     person['name'] = raw_input('Enter name: ')  
  11.     person['age'] = raw_input('Enter age: ')  
  12.     person['phone'] = raw_input('Enter phone number: ')  
  13.     db[pid] = person  
  14.   
  15. def lookup_person(db):  
  16.     """ 
  17.     Query user for ID and desired field, and fetch the corresponding data from 
  18.     the shelf object 
  19.     """  
  20.     pid = raw_input('Enter ID number: ')  
  21.     field = raw_input('What would you like to know? (name, age, phone) ')  
  22.     field = field.strip().lower()  
  23.     print field.capitalize() + ':', \  
  24.         db[pid][field]  
  25.   
  26. def print_help():  
  27.     print 'The available commons are: '  
  28.     print 'store  :Stores information about a person'  
  29.     print 'lookup :Looks up a person from ID number'  
  30.     print 'quit   :Save changes and exit'  
  31.     print '?      :Print this message'  
  32.   
  33. def enter_command():  
  34.     cmd = raw_input('Enter command (? for help): ')  
  35.     cmd = cmd.strip().lower()  
  36.     return cmd  
  37.   
  38. def main():  
  39.     database = shelve.open('database.dat')  
  40.     try:   
  41.         while True:  
  42.             cmd = enter_command()  
  43.             if cmd == 'store':  
  44.                 store_person(database)  
  45.             elif cmd == 'lookup':  
  46.                 lookup_person(database)  
  47.             elif cmd == '?':  
  48.                 print_help()  
  49.             elif cmd == 'quit':  
  50.                 return   
  51.     finally:  
  52.         database.close()  
  53. if __name__ == '__main__': main()  




10.3.8    re模块(正则表达式)

什么是正则表达式?
正则表通常被用来检索、替换那些符合某个模式(规则)的文本。


组:就是放在圆括号内的子模式
对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。每个缓冲区都可以使用 \n访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。

正则表达式中    重复运算符   (*      +        {m,n }   )      默认是贪婪的,既重复运算符会尽可能多的往下匹配
要转成非贪婪的,在 重复运算符后面加一个可选运算符  (  ? ) 

模板系统   看 p201例题
 通过放入具体值从而得到某种完成文本的文件。
1.可以使用正则表达式来匹配字段
2.可以使用eval计算字符串值,(提供scope作用域字典 )。成功的话(匹配项字段就是个表达式)返回一个结果字符串。否则引发SyntaxError异常,跳到使用exec。
3.可以使用exec执行字符串(或其他语句)的赋值操作(假设这时匹配字段是个赋值语句),也使用相同的命名空间字典scope。返回空字符串,因为赋值语句没有对任何内容求值。
4.使用re.sub将求得的值替换。   函数可以作为sub的替换内容,而MatchObject将作为函数的唯一参数,返回的字符串将会替换内容


import fileinput,re
field_pat=re.compile(r'\[(.+?)\]')
scope={}
def replacement(match):
    code=match.group(1)
    try:
        return str(eval(code,scope))
    except SyntaxError:
        exec code in scope
        return ''
lines=[]
for line in fileinput.input('t.txt'):
    lines.append(line)
text=''.join(lines)
print field_pat.sub(replacement,text)
http://blog.youkuaiyun.com/signjing/article/details/34116013
http://blog.youkuaiyun.com/jerry_1126/article/details/41926407

正则表达式全部符号解释

字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。
\n 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值