Differences between revisions 2 and 48 (spanning 46 versions)
Revision 2 as of 2006-09-15 04:59:25
Size: 28507
Editor: ZoomQuiet
Comment:
Revision 48 as of 2009-12-25 07:09:10
Size: 22334
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
'''
Python 绝对简明手册
'''-- [email protected]
::-- ZoomQuiet [[[DateTime(2006-09-15T04:35:33Z)]]]
[[
TableOfContents]]
''' Python 绝对简明手册 '''-- [email protected] ::-- ZoomQuiet [<<DateTime(2006-09-15T04:35:33Z)>>] <<TableOfContents>>
Line 9: Line 6:
[[Include(CPUGnav)]]


= Py2.5 绝对简明手册 =
##[[Include(CPUGnav)]]
Line 14: Line 8:

[http://groups.google.com/group/python-cn/browse_thread/thread/8322e786aa364789/2116205595a4a493#2116205595a4a493 zuroc主动在列表中分享]

PYthon绝对简明手册,初学必备!

  -- For Python2.5

{{{
版本:0.1 beta

作者:张沈鹏

参考:python2.5中文教程

}}}
Http://blog.csdn.net/zuroc

 -- 欢迎指出错误和遗漏,提出建议和意见,请发信到[email protected]




== 语法 ==

=== if ===
{{{#!python
x=int(raw_input("Please enter an integer:"))
if x<0:
    print 'Negative Number'
elif x==0:
    print 'Zero'
else:
    print 'Positive Number'
}}}

=== for ===
{{{#!python
a=['cat','door,'example']
for x in a:
    print x
}}}
#如果要修改a的内容,则用a的副本循环,如:
{{{
for x in a[:] :
    .....................
}}}

{{{#!python
>>>range(10,0,-3)
[10,7,4,1]
a=['cat','door,'example']
for i in range(len(a)):
    print i,a[i]
}}}
= 阅读须知 =

文中使用
{{{
>>>
}}}
作为会命令行中的输出信息的前缀

对于不清楚用用途的函数可以在解释器下面输入
{{{
help(函数名)
}}}
来获取相关信息

另外,自带的文档和google也是不可少的

= 基本语法 =
== if / elif / else ==
{{{

x=int(raw_input("Please enter an integer:"))#获取行输入

if x>0:
    print '正数'
elif x==0:
    print '零'
else:
    print '负数'
}}}
此外C语言中类似"xxx?xxx:xxx"在Python中可以这样写
{{{
>>>number=8
>>>print "good" if 8==number else "bad" #当满足if条件时返回"good",否则返回"bad"
good
}}}

== in ==
in判断 一个数 是否在 一个集合(如:元组,列表等) 中

{{{
if 'yes' in ('y','ye','yes'):print 'ok'
}}}

== for ... in ==
python中没有类似C中的for循环,而是使用for...in来对集合中的每一个元素进行操作
{{{
a=['cat','door','example']
for x in a:
    print x
}}}

如果要修改a的内容,请用a的副本循环(否则不安全),如:
{{{
a=["cat","[email protected]"]
for x in a[:]:
    if len(x)>6:a.insert(0,x)
>>>a
['[email protected]', 'cat', '[email protected]']
}}}

若需要得到循环的次数,参见 函数 range 的用法

== break / continue ==
这两个的用法和C中相同
{{{
for i in range(10):
    if 2==i:continue #结束当前循环,进入下一步循环
    if 6==i:break #跳出循环
    print i
}}}
输出
{{{
0
1
3
4
5
}}}
== while / pass ==
{{{
while True:
    pass #什么也不做
}}}

== is ==
用来比较两个变量是否指向同一内存地址(也就是两个变量是否等价)
而 == 是用来比较两个变量是否逻辑相等
{{{
a=[1,2]
b=[1,2]
>>> a is b
False
>>> a == b
True
}}}

== del ==
用于删除元素
{{{

a=[1,2,3,4,5,6]

del a[0]
a
>>>[2,3,4,5,6]

del a[2:4]
a
>>>[2,3,6]

del a[:]
a
>>>[]

del a
a
#抛出异常
>>>NameError: name 'a' is not defined
}}}

== try ... except ... finally / raise ==
try ... except用于异常处理
{{{
try:
    x=int(raw_input("请输入数字:"))
except ValueError: #可以同时捕获多个异常,写法如except(RuntimeError,ValueError):
    #当输入非数字时
    print"您输入不是数字"
except: #省略异常名,可以匹配所有异常,慎用
    pass
else:#当没有异常时
    print 'result=',result
finally:#和Java中类似。一般用于释放资源,如文件,网络连接。
   print 'finish'
}}}

raise用于抛出异常,可以为自定义的异常类

惯例是以Error结尾的类,同类的异常一般派生自同一个基类(如Exception)
{{{
class MyError(Exception):
    def __init__(self,value):
        self.value=value
    def __str__(self):
        return reper(self.value)
}}}

基类异常可以匹配派生类异常

{{{
try:
    raise Exception("spam","egg")
except Exception,inst:#inst为该异常类的实例,为可选项
    print type(inst) #异常的类型
    print inst
}}}

= 内建类型 =

== None ==
None 表示该值不存在,比如 没有定义返回值 的函数就 返回None

== Ture / False ==
布尔类型,Ture等价于1,False等价于0

== List ==
{{{
>>>test=[1,2,"yes"]
}}}
=== 内建函数 ===
append(x) 追加到链尾

extend(L) 追加一个列表,等价于+=

insert(i,x) 在位置i插入x

remove(x) 删除第一个值为x的元素,如果不存在会抛出异常

reverse() 反转序列

pop([i]) 返回并删除位置为i的元素,i默认为最后一个元素(i两边的[]表示i为可选的,实际不用输入)

index(x) 返回第一个值为x的元素,不存在则抛出异常

count(x) 返回x出现的次数

sort() 排序


例子:
{{{
>>>test=[1,2,"yes"]

>>>test.append(1) #追加到链尾
>>>test
[1, 2, 'yes', 1]

>>>test.extend([ 'no','maybe']) #追加一个列表
>>>test
[1, 2, 'yes', 1, 'no', 'maybe']

>>> test.insert(0,'never') #在位置0插入'never'
>>> test
['never', 1, 2, 'yes', 1, 'no', 'maybe']

>>> test.remove('no') #删除第一个值为"no"的元素,如果不存在会抛出异常
>>> test
['never', 1, 2, 'yes', 1, 'maybe']

>>> test.reverse() #反转序列
>>> test
['maybe', 1, 'yes', 2, 1, 'never']

>>> test.pop() #返回并删除位置为i的元素,i默认为最后一个元素
'never'
>>> test
['maybe', 1, 'yes', 2, 1]

>>> test.index('yes') #返回第一个值为'yes'的元素,不存在则抛出异常
2

>>> test.count(1) #返回1出现的次数
2

>>>test.sort() #排序
>>> test
[1, 1, 2, 'maybe', 'yes']
}}}
=== 切片 ===
从序列中抽取一部分
{{{
>>> test=['never', 1, 2, 'yes', 1, 'no', 'maybe']

>>> test[0:3] #包括test[0],不包括test[3]
['never', 1, 2]

>>> test[0:6:2] #包括test[0],不包括test[6],而且步长为2
['never', 2, 1]

>>> test[:-1] #包括开始,不包括最后一个
['never', 1, 2, 'yes', 1, 'no']

>>> test[-3:] #抽取最后3个
[1, 'no', 'maybe']

>>>test[::-1] #倒序排列
['maybe', 'no', 1, 'yes', 2, 1, 'never']
}}}
=== 列表推导式 ===
可以直接通过for循环生成一个list

{{{
>>>freshfruit=[' banana ',' loganberry ']
>>>[weapon.strip() for weapon in freshfruit]
['banana', 'loganberry']
}}}

说明:strip()是去除字符串两端多于空格,该句是去除序列中的所有字串两端多余的空格

{{{
>>>vec=[2,4,6]
>>>[3*x for x in vec if x>3]
[12, 18]
}}}

{{{
>>>[(x,x**2) for x in vec]
#循环变量要是一个sequence,而[x,x**2 for x in vec]是错误的
[(2,4),(4,16),(6,36)]
}}}

{{{
>>>vec2=[4,3,-9]

>>>[x*y for x in vec for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]

>>>[vec[i]+vec2[i] for i in range(len(vec))]
[6, 7, -3]
}}}

{{{
>>>[str(round(355/113.0,i)) for i in range(1,6)]
#str()是转换类型为可以打印的字符
#round(x,n)表示对x保留n位小数(四舍五入)
['3.1', '3.14', '3.142', '3.1416', '3.14159']
}}}

== 元组 ==
一旦初始化便不能更改的数据结构,速度比list快

{{{
>>>t=1234,5567,'hello' #t=(1234,5567,'hello')的简写

>>>x,y,z=t #拆分操作可以应用于所有sequence
>>>x
1234

>>>u=t,(1,2,3)
>>>u
((1234,5567,'hello'),(1,2,3))

>>>empty=() #空元组
>>>singleton='hi', #单个元素的元组,注意逗号
}}}

通过元组可以很简单的进行数据交换.
比如:
{{{
a=1
b=2
a,b=b,a
}}}

== set ==
set(集合):无序不重复的元素集

{{{

>>>basket = ['apple','orange','apple','pear','apple','banana']

>>>fruit=set(basket)

>>>fruit
set(['orange', 'pear', 'apple', 'banana'])

>>>'orange' in fruit
True

>>>a=set('abracadabew')
>>>a
set(['a', 'c', 'b', 'e', 'd', 'r', 'w'])

>>>b=set('wajgwaoihwb')
>>>b
set(['a', 'b', 'g', 'i', 'h', 'j', 'o', 'w'])
Line 69: Line 345:

break,continue 用法和C++中类似

 


 

=== pass ===
{{{
while True:
    pass #忽略,什么也不做
}}}

{{{#!python
def fib(n=1000):#参数可以有默认值,多个可选参数赋值可以直接写"参数变量名=值"来快速赋值
    """这里给函数写文档注释"""
    a,b=0,1
    while b<n:
       print b
       a,b=b,a+b
}}}
 

#函数可以重命名,如

{{{#!python
f=fib
f(223)
}}}



 

=== in ===
 {{{#!python
if 'yes' in ('y','ye','yes'):print 'ok'
}}}

 

=== 参数格式 **para ===
#参数格式为 **para 表示接受一个字典,为 *para 表示接受一个元组

{{{#!python
def test(para1,*args,**dic):
    print para1
    for arg in args : print arg
    keys=dic.keys()
    keys.sort()
    for key in keys:print key ,':',dic[key]
}}}
 

=== Lambda函数 ===
 {{{#!python
def make_incrementor(n):
    return lambda x: x+n
f=make_incrementor(n)
>>>f(0)
42
>>>f(1)
43
}}}

 

=== List的函数 ===
{{{
append(x) 追加到链尾
extend(L) 追加一个链表
insert(i,x) 在位置i插入x
remove(x) 删除第一个值为x的元素,如果不存在会抛出异常
pop([i]) 返回并删除位置为i的元素,i未给定时默认作用在最后一个元素.[i]表示i为可选的
index(x) 返回第一个值为x的元素,不存在则抛出异常
count(x) 返回x出现的次数
sort() 排序
reverse() 翻转,反转
}}}

`filter(function函数 , sequence序列) `
返回sequence中使filer为true的

`map(function,sequence,[sequence...]) `
返回新的sequence,序列中值为对每个元素分别调用function.

 

`reduce(function,sequence,[init]) `
>>>a-b #差
set(['c', 'r', 'e', 'd'])

>>>a|b #并
set(['a', 'c', 'b', 'e', 'd', 'g', 'i', 'h', 'j', 'o', 'r', 'w'])

>>>a&b #交
set(['a', 'b', 'w'])

>>>a^b #(并-交)
set(['c', 'e', 'd', 'g', 'i', 'h', 'j', 'o', 'r'])
}}}
== dict ==

字典:关键字为不可变类型,如字符串,整数,只包含不可变对象的元组.

列表等不可以作为关键字.

如果列表中存在关键字对,可以用dict()直接构造字典.而这样的列表对通常是由列表推导式生成的.

{{{

>>>tel={'jack':4098,'sape':4139}

>>>tel['guido']=4127

>>>tel
{'sape': 4139, 'jack': 4098, 'guido': 4127}

>>>tel['jack'] #如果jack不存在,会抛出KeyError
4098
>>>a.get("zsp",5000) #如果"zsp"为tel的键则返回其值,否则返回5000

>>>del tel['sape'] #删除键'sape'和其对应的值
>>>tel.keys() #复制一份键的副本,同理tel.items()为值的副本
['jack', 'guido']

>>>"jack" in tel #判断"jack"是否tel的键
True
>>>"zsp" not in tel
True

>>>for k,v in tel.iteritems():print k,v #同理tel.iterkeys()为键的迭代器,tel.itervalues()为值的迭代器
jack 4098
guido 4127

>>>tel.copy() #复制一份tel
{'jack': 4098, 'guido': 4127}

>>> tel.fromkeys([1,2],0) #从序列生成并返回一个字典,其值为第二个参数(默认为None),不改变当前字典
{1: 0, 2: 0}

>>>tel.popitem() #弹出一项
('jack', 4098)

}}}

= 函数相关 =

== 函数定义 / 参数默认值 ==
{{{

def fib(n=2,a=1):#参数可以有默认值
    """这里给函数写文档注释"""
    for i in range(n):
        print a


>>>f=fib #可以用一个变量表示函数
>>>f(3)
1
1
1

>>>fib(a=2) #多个可选参数赋值可以直接写"参数变量名=值"来快速赋值
2
2
}}}

== Lambda函数 ==
一种无名函数的速写法
{{{

def make_incrementor(n):
    return lambda x: x+n

f=make_incrementor(n)
#f等价于
#def f(x):
# return x+n

}}}

== 不定长参数 *para,**para ==
参数格式为 *para 表示接受一个元组

为 **para 表示接受一个字典

*para要在**para之前

{{{

def test(*args,**dic):
    for arg in args :
        print arg
    for k,v in dic.iteritems():
        print k ,':',v

>>> test("yes",1,2,me="张沈鹏",where="中国") #"yes",1,2传递给元组;me="张沈鹏",where="中国"传递给字典
yes
1
2
me : 张沈鹏
where : 中国
}}}

== @ 装饰器 ==
@A
def B:pass
等价于
def B:pass
B=A(B)
即将函数B作为参数传给参数A
{{{
from time import time
#测试运行时间
def cost_time(func):
    def result(*args,**dic):
        beign=time()
        func(*args,**dic)
        print "cost time : ",time()-beign
    return result

@cost_time
def show(n):
    for x in range(n):print x

>>> show(10)
0
1
2
3
4
5
6
7
8
9
cost time : 0.0469999313354
}}}

== 生成器表达式 ==
生成器表达式:类似于没有中括号的列表推导式,可用在参数中
{{{
>>>sum(i*i for i in range(10))
285

>>>unique_words=set(word for line in page for word in line.split())#page为打开的文件

>>>data='golf'

>>>list(data[i] for i in range(len (data)-1,-1,-1))
['f','l','o','g']

}}}
== yield ==
每次调用返回一个值,并记录当前执行位置所有的变量
{{{
def reverse(data):
    for index in range(len(data)-1,-1,-1):
        yield data[index]

for char in reverse("golf"):
    print char,
}}}
输出
{{{
f l o g
}}}

= 常用函数 =
== eval ==
对字符串参数运算,求值
{{{
>>> eval("1 + 2*3") #可以方便的用来做四则运算
7
>>> a=1
>>> eval('a+1') #可以访问变量
2
}}}
== exec ==
将字符串参数作为python脚本执行
{{{
>>> exec('a="Zsp"')
>>> a
'Zsp'
}}}
== execfile ==
和exec类似,不过是用来打开一个文件,并作为python脚本执行

== dir ==
显示对象的所有属性(即可以用"."操作直接访问)
{{{
>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
}}}
== help ==
help(类/函数) 返回相应对象的文档字符串
{{{
>>> help(vars)
Help on built-in function vars in module __builtin__:

vars(...)
    vars([object]) -> dictionary
    
    Without arguments, equivalent to locals().
    With an argument, equivalent to object.__dict__.
}}}

== len ==
返回序列/字典的长度
{{{
>>> len([1,2,3])
3
}}}

== print ==
输出字符串
用法演示:
{{{
print "Today ", #加逗号,输出后不换行

name="ZSP"

print name,"cost $",10 #输出多个变量

print "hello,%s!"%name #%s 表示用str转化为字符串

for x in xrange(1,11):
    print '%2d %3d' % (x,x*x) #小数输出如 %5.3f
}}}
对于字典可以用变量名来直接格式化,如:
{{{
>>>table={'Sjoerd':4127,'Jack':4098,'Dcab':8637678}
>>>print 'Jack:%(Jack)d; Sjoerd:%(Sjoerd)d; Dcab:%(Dcab)d' %
table
Jack:4098; Sjoerd:4127; Dcab:8637678
}}}
同时,函数vars()返回包含所有变量的字典,配合使用,无坚不摧!

== raw_input ==
{{{
x=raw_input("Please enter an sentence:") #将输入的内容赋值给x
}}}
== range ==
{{{
range(10,0,-3)#参数的含义为起点(默认为0),终点(不含终点),步长(默认为1)
>>>[10,7,4,1]
}}}

和for...in配合使用
{{{
a=['cat','door','example']
for i in range(len(a)):#len()函数为求序列的长度
    print i,a[i]
}}}


== filter ==
filter(function , sequence)
返回序列,为原序列中能使function返回true的值
{{{
>>>a=[1,2,3,4]
>>>filter(lambda x:x%2,a)
[1, 3]
}}}

== map ==

map(function,sequence,[sequence...])

返回序列,为对原序列每个元素分别调用function获得的值.

可以传入多个序列,但function也要有相应多的参数,如

map(lambda x,y,z:x+y+z,range(1,3),range(3,5),range(5,7))

计算过程为

1+3+5=9

2+4+6=12

返回[9,12]

== reduce ==

reduce(function,sequence,[init])
Line 160: Line 645:
 * 第1个结果=function(sequence[0],sequence[1])
 * 第2个结果=function(第1个结果,sequence[2])
 * 返回最后一个计算得值
 * 如果有init,则先调用

`function(init,sequence[0]) `
sequence只有一个元素时,返回该元素,为空时抛出异常.

=== 链表推导式 ===
{{{
freshfruit=[' banana ',' loganberry ']
>>>[weapon.strip() for weapon in freshfruit]
['banana','loganberry']
vec=[2,4,6]
>>>[3*x for x in vec if x>3]
[12,18]
>>>[(x,x**2) for x in vec] #一个元素一定要是一个sequence,而
[x,x**2 for x in vec]是错误的
[(2,4),(4,16),(6,36)]
vec2=[4,3,-9]
[x*y for x in vec for y in vec2]
[vec[i]+vec2[i] for i in range(len(vec))]
[str(round(355/113.0,i)) for i in range(1,6)] #str()是转换类型为可以打印的字符
}}}

 

=== del ===

{{{#!python
a=[1,2,3,4,5,6]
del a[0]
>>>a
[2,3,4,5,6]
del a[2:4]
>>>a
[2,3,6]
del a[:]
>>>a
[]
del a
>>>a
}}}
抛出异常

 



=== 元组 ===
{{{
t=1234,5567,'hello'
x,y,z=t #拆分操作可以应用于所有sequence
>>>x
1234
u=t,(1,2,3)
>>>u
((1234,5567,'hello'),(1,2,3))
empty=() #空元组
singleton='hi', #单个元素的元组
}}}


=== set ===
set(集合):无序不重复的元素集

{{{#!python
basket = ['apple','orange','apple','pear','apple','banana']
fruit=set(basket)
>>>fruit
set(['orange', 'pear', 'apple', 'banana'])
>>>'orange' in fruit
True
a=set('abracadabew')
>>>a
set(['a', 'c', 'b', 'e', 'd', 'r', 'w'])
b=set('wajgwaoihwb')
>>> b
set(['a', 'b', 'g', 'i', 'h', 'j', 'o', 'w'])
>>> a-b #差
set(['c', 'r', 'e', 'd'])
>>> a|b #并
set(['a', 'c', 'b', 'e', 'd', 'g', 'i', 'h', 'j', 'o', 'r', 'w'])
>>> a&b #交
set(['a', 'b', 'w'])
>>>a^b #(并-交)
set(['c', 'e', 'd', 'g', 'i', 'h', 'j', 'o', 'r'])
}}}


=== dict ===

字典:关键字为不可变类型,如字符串,整数,只包含不可变对象的元组.链表等不可以作为关键字.如果链表中存在关键字对,可以用dict()直接构造字典.而这样的链表对通常是由链表推导式生成的.

{{{#!python
tel={'jack':4098,'sape':4139}
tel['guido']=4127
>>> tel
{'sape': 4139, 'jack': 4098, 'guido': 4127}
>>>tel['jack']
4098
del tel['sape']
>>>tel.keys()
['jack', 'guido']
>>>tel.has_key('jack')
True
knight=['gallahad':'the pure','robin':'the brave']
for k,v in knight.iteritems():
    print k,v
}}}
输出:

{{{#!python
gallahad the pure
robin the brave

}}}



enumerate()返回索引位置和对应的值

{{{#!python
for i,v in enumerate(['tic','tac','toe'])
    print i,v
}}}

输出:
0 tic


1 tac


2 toe

 

=== zip ===
zip用于多个sequence的循环

{{{#!python
questions=['name','quest','favorite color']
answers=['lancelot','the holy grail','blue']
for q,a in zip(questions,answers):
    print 'What is your %s ? It is %s.'%(q,a)
}}}
输出:

{{{#!python
What is your name ? It is lancelot.
What is your quest ? It is the holy grail.
What is your favorite color ? It is blue.
}}}
 

=== reversed反向循环 ===
 

{{{#!python
for i in reversed(range(1,4)):
    print i
}}}

输出:


3


2


1

 

=== sorted排序 ===
 

 

=== sequence比大小 ===

list<string<tuple(因为字母表中l在s前...)

同类比大小按照字典序

 

 

=== 导入模块 ===
 

模块的查找路径


1.当前的目录


2.环境变量PYTHONPATH所指的目录列表


3.环境变量PATH表示的目录


4.python解释器的安装目录

 

如将代码保存上述的一个目录中的的fibo.py文件中,便可以

{{{#!python
import fibo
fibo.function().............
}}}

如果想直接使用fibo.function可以重命名这个函数,如

{{{#!python
f=fibo.function
f()
}}}
也可以{{{#!python
form fibo import function
function()
}}}

甚至可以`form fibo import * `


可以 `form 包.子包.模块 imort 函数 `
 * 第1个结果=function(sequence[0],sequence[1])
 * 第2个结果=function(第1个结果,sequence[2])
 * 返回最后一个计算得值
 * 如果有init,则先调用{{{function(init,sequence[0]) }}}
 * sequence只有一个元素时,返回该元素,为空时抛出异常.

{{{reduce(lambda x,y:x+y,range(3),99)}}}
的计算为

99+0=99 => 99+1=100 => 100+2=102

返回102

注:实际使用中用内建函数sum来完成这个累加更合适,如这里等价sum(range(3),99)

== zip ==
zip用于多个sequence的循环
{{{
questions=['name','quest','favorite color']
answers=['lancelot','the holy grail','blue']

for q,a in zip(questions,answers):
    print 'What is your %s ? It is %s.'%(q,a)
}}}

输出:
{{{
What is your name ? It is lancelot.
What is your quest ? It is the holy grail.
What is your favorite color ? It is blue.
}}}

== reversed反向循环 ==
{{{

for i in reversed(range(1,4)):
    print i

}}}
输出:
{{{
3
2
1
}}}
== sorted排序 ==
返回一个有序的新序列
{{{
>>>sorted([2,5,1,4])
[1, 2, 4, 5]
}}}
== enumerate 返回索引位置和对应的值 ==
{{{
for i,v in enumerate(['tic','tac','toe'])
    print i,v
}}}
输出:
{{{
0 tic
1 tac
2 toe
}}}
== open/文件操作 ==
f=open('/tmp/hello','w')

#open(路径+文件名,读写模式)

#读写模式:r只读,r+读写,w新建(会覆盖原有文件),a追加,b二进制文件.常用模式

如:'rb','wb','r+b'等等

f.read([size]) size未指定则返回整个文件,如果文件大小>2倍内存则有问题.f.read()读到文件尾时返回""(空字串)

file.readline() 返回一行

file.readline([size]) 返回包含size行的列表,size 未指定则返回全部行

for line in f: print line #通过迭代器访问

f.write("hello\n") #如果要写入字符串以外的数据,先将他转换为字符串.

f.tell() 返回一个整数,表示当前文件指针的位置(就是到文件头的比特数).

f.seek(偏移量,[起始位置])

用来移动文件指针

偏移量:单位:比特,可正可负

起始位置:0-文件头,默认值;1-当前位置;2-文件尾

f.close() 关闭文件

= 模块化 =

== 导入模块 ==
模块的查找路径

1.当前的目录

2.环境变量PYTHONPATH所指的目录列表

3.python解释器的安装目录

如将代码保存上述的一个目录中的的fibo.py文件中,便可以

{{{
import fibo
fibo.function()
}}}
如果想直接使用fibo.function可以重命名这个函数,如

{{{
f=fibo.function
f()
}}}
也可以

{{{
form fibo import function
function()
}}}
甚至可以{{{form fibo import * }}}

可以 {{{form 包.子包.模块 imort 函数 }}}
Line 396: Line 773:
   === 包 ===


引用推荐写法为 

`form 包 import 模块`
== 包 ==
引用推荐写法为

{{{form 包 import 模块}}}
Line 410: Line 782:
Line 413: Line 784:
 __init__.py
 
Formats/
  __init__.py
  
wavread.py
  wavwrite.py
  mp3read.py
  mp3write.py
  wmaread.py
  wmawrite.py
 Effects/
  __init__.py
  
echo.py
  surround.py
  reverse.py
}}}

只有当__init__.py存在时python才将该文件夹视为一个包,该文件可以为空文件
一般在__init__.py文件中定义一个__all__表,包含要import *时要导入的模块.
如Sound/Effects/__init__.py可以有如下内容

`__all__=["echo","surround","reverse"]`
        __init__.py
        
Formats/
                __init__.py
                
wavread.py
                wavwrite.py
                mp3read.py
                mp3write.py
                wmaread.py
                wmawrite.py
        Effects/
                __init__.py
                
echo.py
                surround.py
                reverse.py
}}}

只有当__init__.py存在时python才将该文件夹视为一个包.

该文件可以为空文件 一般在__init__.py文件中定义一个__all__表,包含要import *时要导入的模块. 如Sound/Effects/__init__.py可以有如下内容

{{{__all__=["echo","surround","reverse"]}}}
Line 440: Line 810:
`form 包.子包 imort 模块`

简写为
`imort 模块`


=== 格式化输出 ===
{{{
for x in xrange(1,11):
    print repr(x).rjust(2),repr(x*x).rjust(3)
    #repr是将变量类型转换为可以被编译器处理的文字格式
    #rjust是调整宽度为参数个字符,r表示右对齐;ljust为左对齐,ljust(n)[:n]可
以截断输出;center为居中
    #zfill()可以向数值表达式的左侧填充0
 }}}

=== 等效代码 ===
 
{{{
for x in xrange(1,11):
    print '%2d %3d' % (x,x*x)
#%2d和%3d之间要有空格,d表示为整数
#%10s 表示用str转化为字符串
#小数输出如 %5.3f
}}}

对于字典可以用变量名来直接格式化,如:
{{{
>>>table={'Sjoerd':4127,'Jack':4098,'Dcab':8637678}
>>>print 'Jack:%(Jack)d; Sjoerd:%(Sjoerd)d; Dcab:%(Dcab)d' %
table
Jack:4098; Sjoerd:4127; Dcab:8637678
}}}
 

同时,函数vars()返回包含所有变量的字典,配合使用,无坚不摧!

 



 

=== 读写文件: ===

 

f=open('/tmp/hello','w')

#open(路径+文件名,读写模式)

#读写模式:r只读,r+读写,w新建(会覆盖原有文件),a追加,b二进制文件.常用模式

如:'rb','wb','r+b'等等

 

f.read([size]) size未指定则返回整个文件,如果文件大小>2倍内存则有问题.f.read()读到文件尾时返回""(空字串)

file.readline() 返回一行

file.readline([size]) 返回包含size行的列表,size 未指定则返回全部行

 

for line in f: #交换通道

    print line

 

f.write("hello\n") #如果要写入字符串以外的数据,先将他转换为字符串.

 

f.tell() 返回一个整数,表示当前文件指针的位置(就是到文件头的比特数).

 

f.seek(偏移量,[起始位置])

用来移动文件指针

偏移量:单位:比特,可正可负

起始位置:0-文件头,默认值;1-当前位置;2-文件尾

 

f.close() 关闭文件

 

----------------------------------------------------------

 

pickle 序列化/保存对象/封装

 

pickle.dump(x,f) #把文件对象f保存到x变量中

x=pickle.load(f) #还原这个对象

 

 

----------------------------------------------------------

 

try:

    ..............

except 异常类型:

#如果有多个异常类型,可以将他们放在括号()中

#如except(RuntimeError,TypeError,NameError):

    ...............

 

最后一个异常名可以省略异常类型,作为通配项将所有异常pass.慎用!!!

 

在except后可以包含一个else

 

raise可以抛出异常,同时可以附带异常参数

try:

    rasie Exception('message1','message2')

    #只有一个参数时也可以这样写rasie Exception,'message1'

except Exception,inst:

    #inst是该异常类的一个实例

 

    print inst.args

    #打印出参数名

 

    print inst #直接打印__str__属性

 

    x,y=inst

    print 'x=',x

    print 'y=',y

 

如果抛出异常没有指定参数,则捕获异常时的参数包含的是该异常的默认信息

>>>try:

            1/0

      except ZeroDivisionError,detail:

            print 'Handling run-time error:',detail

 

Handling run-time error:integer division or modulo by zero

 

----------------------------------------------------------

 

自定义异常:惯例是以Error结尾的类,同类的异常一般派生自同一个基类,基类异常可以匹配派生类异常

 

class MyError(Exception):

    def __init__(self,value):

       self.value=value

    def __str__(self):

       return reper(self.value)

 

try:

    raise MyError(2,2)

except MyError,e:

    print 'My exeception occurred,value',e.value

>>>

My exeception occurred,value 4

 

----------------------------------------------------------

 

finally:和C++中类似,即使是break,continue或return后一样会执行。一般用于释放资源,如文件,网络连接。

 

def divide(x,y):

    try:

       result=x/y

    except ZeroDivisionError:

       print "除以0"

     else:

       print '结果是',result

    finally:

       print "计算完成!"

 

----------------------------------------------------------

 

with #with可以帮助你自动释放资源

 

with open('myfile.txt') as f:

    for line in f:

       print line

#该文件会自动被释放

 

----------------------------------------------------------



初识类

 

class ClassName:

    "类文档,可以通过类名.__doc__访问"

    

    #类的私有变量是至少以双下划线开头,最多以单下划线结尾的类变量,调用时会变量名会被混淆成 _ClassName__变量名

    __i=12345

    

    def f(self)

       return "hello world"

   

   def __init(self)__:

     "构造函数,可以初始化变量,可以有参数"

     #可以通过self调用当前类的函数和数据

     self.data=[]



#创建类实例

x=ClassName()



#给类的方法重命名

xf=ClassName.f



----------------------------------------------------------



类单继承


{{{form 包.子包 imort 模块}}}

简写为 {{{imort 模块}}}

== 面向对象 ==
=== 概要 ===
{{{
class ClassName:
    "类文档,可以通过类名.__doc__访问"
    def f(self):#self为每个类函数的必要的一个参数,可以通过它来访问当前实例
        return self.content

    def __init__(self,word=''):#构造函数
        #构造函数,可以初始化变量,可以有参数"
        self.content=word
        self.__name=word #私有变量,以"__"开头,不以"__"结尾的变量
}}}
创建类实例
{{{x=ClassName("good")}}}

=== 类继承 ===
Line 760: Line 832:

 ....................................

 
    pass
Line 769: Line 838:


派生类的函数会覆盖基类的同名函数,如果想扩充而不是改写基类的函数,可以这样调用基类函数
派生类的函数会覆盖基类的同名函数

如果想扩充而不是改写基类的函数,可以这样调用基类函数
Line 776: Line 845:



----------------------------------------------------------



类多继承//小心使用



class DerivedClassName:(Base1,Base2,Base3):

.................



对于一个函数的解析规则是深度优先,先是Base1,然后是Base1的基类,诸如此类.

 

----------------------------------------------------------



Iterators 迭代器



for element in [1,2,3]:

 print element

98 print element

for key in {'one':1,'two':2}:

 print key

for line in open("my.txt"):

 print line



在容器中定义next()逐一返回元素,并在迭代完成时抛出StopIteration异常,然后定义__iter__()返回self,便可以for...in循环



用Generators(生成器)可以快速定义for...in循环.

def reverse(data):

 for index in range(len(data)-1,-1,-1):

  yield data[index]

#yield会自动创建next()和__iter__(),每次调用next()时yield会进行下一步循环,并在yield处返回值



----------------------------------------------------------



生成器表达式:类似于没有中括号的链表推导式,可用在参数中



>>>sum(i*i for i in range(10))

285



>>>xvec=[10,20,30]

>>>yvec=[7,5,3]

>>>sum(x*y for x,y in zip(xvec,yvec))

 260



>>>from math import pi,sin

>>>sine_table=dict((x,sin(x*pi/180) for x in range(1,91))



>>>unique_words=set(word for line in page for word in line.split())



>>>data='golf'

>>>list(data[i] for i in range(len (data)-1,-1,-1))

['f','l','o','g']



----------------------------------------------------------



== 常用函数不完全手册
 ==


dir(模块) #来获取模块的函数/变量列表

help(模块/函数) #获取相关的帮助



----------------------------------------------------------

模块:os

 与操作系统相关的函数



例:

import os

os.getcwd() #当前脚本的工作目录

os.chidr() #改变当前工作目录



----------------------------------------------------------

 

模块:shutil

 目录和文件管理的接口



例:

import shutil

shutil.copyfile('data.txt','archive.txt')

shutil.move('/build/a.txt','b.txt')

----------------------------------------------------------

 

模块:glob

生成文件列表,支持通配符



例:

import glob

>>>glob.glob('*.py')

['primes.py','random.py','quote.py']



----------------------------------------------------------



模块:sys

提供命令行参数,错误输出重定向和脚本终止



例:

命令行参数

如执行python demo.py one,two,three后

import sys

print sys.argv

会输出

['demo.py','one','two','three']



终止脚本

sys.exit()



错误输出重定向,可以在stdout被重定向时显示错误信息

>>>sys.stderr.write('Warning , log file not found starting a new one\n')

Warning , log file not found starting a new one



----------------------------------------------------------

 

模块:re

字符正值表达式匹配



例:

import re

>>>re.findall(r'\bf[a-z]*','which foot or hand fell fastest')

['foot','fell','fastest']



>>>re.sub(r'(\b[a-z]+)\l',r'\l','cat in the hat')

'cat in the hat



----------------------------------------------------------



模块:math

为浮点运算提供了底层C函数库的访问



例:

>>>math.cos(math.pi/4.0)

0.70710678118654757

>>>math.log(1024,2)

10.0

 

----------------------------------------------------------



模块:random

生成随机数



例:

import random

>>>random.choice(['apple','pear','banana'])

'apple'



>>> random.sample(xrange(100),10) #随机值不会重复

[20,42,12,44,57,88,93,80,75,56]



>>>random.random()

0.26676389968666669



>>> random.randrange(10)

7



----------------------------------------------------------

 

模块:urblib2

打开url地址



例:

for line in urllib2.urlopen('http:\\www.python.org\')

 print line



----------------------------------------------------------



模块:smtplib

发送电子邮件



例:

sever=smtplib.smtp('localhost')

sever.sendmail('[email protected]','[email protected]')

"""TO:[email protected]

From:[email protected]

"""

sever.quit()



----------------------------------------------------------

 

模块:datetime

时间日期相关算法以及格式化输出

 

例:

from datetime import date

now=date.today

>>>now

datetime.date(2006, 9, 13)



>>>now.strftime("%m-%d-%y . %d %b %Y is a %A on the %d day of %B . ")

'09-13-06 . 13 Sep 2006 is a Wednesday on the 13 day of September . '



birthday=date(1986,6,30)

age=now-birthday

>>> age.days

7380



----------------------------------------------------------



模块:zipfile / tarfile

数据打包和压缩,支持格式:zlib,gzip,bz2,zipfile和tarfile

 

例:

import zlib

s="which which which which"

 t=zlib.compress(s)

>>>len(s)

23

>>>len(t)

16

>>>zlib.decompress(t)

"which which which which"

>>>zilb.crc(32)

-487390043

 

----------------------------------------------------------

 

模块:timeit

性能测试



例:

from timeit import Timer

#Timer的第一个参数是要测试时间的语句,第二个参数是初始化

#timeit的参数是测试语句的执行次数,默认执行1000000次

>>> Timer('t=a;a=b;b=t','a=1;b=2').timeit()

0.31399409701512582

>>> Timer('a,b=b,a','a=1;b=2').timeit()

0.247945758469313663



模块:profile和pstats提供了对更大代码块的测量工具



----------------------------------------------------------

 

模块:doctest

质量测试,测试代码.

他将对函数文档中的测试代码进行测试,他使文档的撰写和软件的测试融合了起来



例:

def average(values):

 """Computer average

#注意>>> 和测试代码之间要空一格,测试结果前面不要有空格

>>> print average([10,90,53])

51.0

 """

 return sum(values,0.0)/len(values)



import doctest

doctest.testmod()

----------------------------------------------------------

模块:unittest

可以在一个独立的文件中提供一个更全面的代码测试.



例:

import unittest

class TestStatisticalFunctions(unittest.TestCase):



 def test_average(self):

  self.assertEqual(average([20,30,70]),40.0)

  self.assertEqual(round([1,5,7]),1)

  self.assertRaises(ZeroDivisionError,average,[])

  self.assertRaises(TypeError,average,20,30,70)



unittest.main()



----------------------------------------------------------



其他一些常用模块



xmlrpclib和SimpleXMLRPCServer可以在琐碎的任务中调用远程过程



email可以构建和解析复杂的消息结构,包括附件,文字编码和头协议等等



xml.dom和xml.sax



csv通用数据库中直接读写



gettext,locale,codecs国际化(i18n)支持



----------------------------------------------------------



模块:pprint

美化打印(pretty printer)



例:

import pprint

t=[[ ['blue','cyan'] ,['green','red'],'yellow' ],'while']

>>> pprint.pprint(t,width=30)

[[['blue', 'cyan'],

  ['green', 'red'],

  'yellow'],

 'while']



----------------------------------------------------------



模块:textwrap

格式化段落来适应行宽



例:

import textwrap



doc="""Object for wrapping/filling text. The public interface consists of the wrap() and fill() methods; the other methods are just there for subclasses to override in order to tweak the default behaviour. If you want to completely replace the main wrapping algorithm, you'll probably have to override _wrap_chunks()."""



>>> print textwrap.fill(doc,width=40)

Object for wrapping/filling text. The

public interface consists of the wrap()

and fill() methods; the other methods

are just there for subclasses to

override in order to tweak the default

behaviour. If you want to completely

replace the main wrapping algorithm,

you'll probably have to override

_wrap_chunks().



----------------------------------------------------------

 

模块:locale

国际化



例:

import locale

locale.setlocale(locale.LC_ALL,'English_United States.1252')

x=1234567.8

>>>locale.format("%d",x,grouping=True)

'1,234,567'



conv=locale.localeconv()

>>> locale.format("%s%.*f",(conv['currency_symbol'],conv['frac_digits'],x),grouping=True)

'$1,234,567.80'

----------------------------------------------------------

模块:string.template

生成句子的模版,输入"张沈鹏",生成"大家好,我的名字是张沈鹏."



例:

from string import Template

t=Template('${village}flok send $$10 to $cause')

t.substitute(village='Nottingham',cause='the ditch fund')

'Nottinghamflok send $10 to the ditch fund'



当占位符没有提供时substitute会抛出KeyError的异常

而safe_substitute可以在占位符提供不完整时保留占位符,而不抛出异常



----------------------------------------------------------



模块:struct

用于读取二进制格式的文件



例:#H 代表unsigned short , read(2)因为unsigned short占2个bytes

#L 代表4字节的无符号整数



data=open('myfile.zip','rb').read()

start=0

for i in xrange(3):

 start+=14

 fields=struct.unpack('LLLHH',data[start:start+16])

 crc32,comp_size,uncompsize,filenamesize,extra_size=fields



 start+=16

 filename=data[start:start+filenamesize]



 start+=filenamesize

 extra=data[start:start+extra_size]



 print filename,hex(crc32),comp_size,uncomp_size

 

 start+=extra_size+comp_size #下一个头文件



----------------------------------------------------------

 

模块:threading

线程



例:

import threading,zipfile

class AsyncZip(threading.Thread)

 def __init__(self , infile , outfile):

  self.infile=infile

  self.outfile=outfile



 def run(self):

  f=zipfile.ZipFile(self.outfile , 'w' , zipfile.DEFLATED)

  f.write(self.infile)

  f.close()

  print 'Finished background zip of: ', self.infile



background=AsyncZip('mydata.txt','myarchive.zip')



background.start()

print 'The main program continues to run in foreground'



background.join() #Wait for the background task finish

print 'Main program waitwd until background was done .'

----------------------------------------------------------



 模块:Queue

 协多线程的资源调用



----------------------------------------------------------

 

模块:logging

日志



例:

import logging

logging.debug('Debugging information')



logging.info('Information message')



logging.warning('Warning:coinfig file %s not found','server.conf')



logging.error('Error occurred')



logging.critical('Critical error -- shutting down')


{{{
class A:
    def hi(self):
        print "A"
class B:
    def hi(self):
        A.hi(self)
        super(B).hi() #通过super关键字可以获得当前类的基类
        print "B"

B().hi()
}}}
输出
{{{
A
B
}}}

=== 多重继承 ===
类多继承
{{{
class DerivedClassName(Base1,Base2,Base3):
    pass
}}}
对于该类函数的解析规则是深度优先,先是Base1,然后是Base1的基类,诸如此类.
{{{
class A:
    def hi(self):
        print "A"

class B:
    def hi(self):
        print "B"
        
class C(A,B):
    pass

C().hi()
}}}
Line 1590: Line 885:

WARNING:root:Warning:config file server.conf not found

ERROR:root:Error occurred

CRITICAL:root:Critical error -- shutting down



----------------------------------------------------------

 

模块:wearef

不创建引用来跟踪对象



例:

>>>import weakref,gc

>>>class A :

...def __init__ (self,value):

... self.value=value

...def __repr__(self):

... return str(self.value)

...

>>>a=A(10) #create a reference

>>>d=weakref.WeakValueDictionary()

>>>d[’primary’]=a #does not create a reference

>>>d[’primary’] #fetch the object if it is still alive

10

>>>del a #remove the one reference

>>>gc.collect() #run garbage collection right away

0

>>>d[’primary’] #entry was automatically removed

Traceback(mostrecentcalllast):

File "<pyshell#108>",line1,in-toplevel-

d[’primary’] #entry was automatically removed

File "C:/PY24/lib/weakref.py" , line46 , in __getitem__

o = self.data[key]()

KeyError:’primary’



----------------------------------------------------------



 模块:array

 类似链表的对象,比默认的链表更紧凑,仅用来存储数据



 例:

 from array import array

#存储双字节无符号整数,编码类型为H a=array('H',[4000,10,700,22222])

>>> sum(a)

26932

>>>a[1:3]

array('H',[10,700])

----------------------------------------------------------

 

模块:collections

提供了类似链表的deque对象,它从左边添加(append)和弹出(pop)更快,但在内部查询更慢.适用于队列的实现和广度优先树的搜索



例:

from collection import deque

d=deque["task1","task2","task3"]

d.append("task4")

>>>print "Handling",d.popleft()

Handling task1



unsearched=deque([start_nodel])

def breadth_first_search(unsearched):

 node=unsearch.popleaf()

 for m in gen_moves(node):

  if is_goal(m):

   return m

  unsearched.append(m)

----------------------------------------------------------

 

模块:bisect

操作存储链表



例:

import bisect

scores=[(100,'perl'),(200,'tcl'),(400,'lua'),(500,'python')]

bisect.insort(scores,(300,'ruby'))

>>>scores

[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]



----------------------------------------------------------

 

模块:heapq

提供基于正常链表的堆实现,最小总是第一个元素(0点),对希望循环访问最小元素但不想执行完整堆排列非常有用



例:

from heapq import heapify,heappop,heappush

data=[1,3,5,6,7,8,9,65,0]

heapify(data)

heappush(data,-5)

[heappop(data) for i in range(3) ]



>>> [heappop(data) for i in range(3) ]

[-5, 0, 1]



----------------------------------------------------------



 模块:decimal

提供了一个Decimal数据类型,用于浮点数高精度的计算,高精度使Decimal可以执行二进制浮点数无法进行的模运算和等值测试



例:

from decimal import *



>>>Decimal('0.70')*Decimal('1.05'))

0.7350



>>> .70*1.05

0.73499999999999999



>>>sum([Decimal('0.1')*10==Decimal('1.0')])
{{{
A
}}}
== 操作符重载 ==
通过定义类的一些约定的以"__"开头并结尾的函数,可以到达重载一些特定操作的目的,下面是是一些常用的重载

=== __str__ / __unicode__ ===
当print一个对象实例时,实际是print该实例__str__()函数的返回值.
{{{
class A:
    def __str__(self):
        return "A"
    def __unicode__(self):
        return "uA"

print A()
print unicode(A())
}}}
输出
{{{
A
uA
}}}

__unicode__和__str__类似,不过返回Unicode字符串.

=== 比较操作 ===
x<y x.__lt__(y)

x<=y x.__le__(y)

x==y x.__eq__(y)

x!=y 或 x<>y x.__ne__(y)

x>y x.__gt__(y)

x>=y x.__ge__(y)

__cmp__( self, other)
用来简化比较函数的定义
self < other返回负数,相等时返回0,self>other时返回正数

{{{
class A:
    def __init__(self,i):
        self.i=i
    def __cmp__(self,other):
        return self.i-other.i

print A(1)>A(2)
}}}
输出
{{{
False
}}}
=== __iter__ ===
for ... in 循环即就是通过这个函数遍历当前容器的对象实例
可配合yield方便的编写这个函数(参见基本语法yield)
{{{
class A:
   def __init__(self,n):
       self.n=n
   def __iter__(self):
       n=self.n
       while n:
           m=n%2
           n/=2
           yield m

for i in A(5):
    print i,
}}}
输出
{{{
1 0 1
}}}

另有一种繁琐的实现:
返回一个可以通过next()函数遍历的对象,当结束时抛出StopIteration异常

== 类相关函数 ==
=== type ===
返回对象的类型
{{{
>>> type("")
<type 'str'>
>>> type("")==str
Line 1805: Line 975:


>>>sum([0.1*10])==1.0
>>> type([])
<type 'list'>
>>> type([])==list
True

>>> type({})
<type 'dict'>

>>> type(())
<type 'tuple'>

>>> class A:pass

>>> type(A)
<type 'classobj'>

>>> type(A())
<type 'instance'>

>>> import types #在types模块中有许多类型的定义

>>> type(A)==types.ClassType
True

}}}

=== getattr / hasattr /delattr ===
getattr:通过类实例和一个字符串动态的调用类函数/属性
{{{
class A:
    def name(self):
        return "ZSP"
    def hello(self):
        return "nice to meet me ."

def say(obj,attr):
    print getattr(obj,attr)()

a=A()
say(a,"name")
say(a,"hello")
}}}
输出
{{{
ZSP
nice to meet me .
}}}
hasattr 用来判断实例有无该函数/属性

delattr 用来删除实例的函数/属性
=== property ===
通过值的方式调用实例无参函数
{{{
class A(object):
    def __init__(self): self._x = None
    def getx(self): return self._x
    def setx(self, value): self._x = value
    def delx(self): self._x=None
    x = property(getx, setx, delx, "I'm the 'x' property.")
a=A()
print a.x

a.x="ZSP"
print a.x

del a.x
print a.x
}}}
输出
{{{
None
ZSP
None
}}}
可以方便的定义一个只读属性
{{{
class A(object):
    @property
    def x(self): return "Property"
}}}
调用
{{{
>>>a=A()

>>>print a.x
Property

>>>a.x="ZSP" #只读属性,不能更改
Traceback (most recent call last):
  File "D:\Profile\Untitled 2.py", line 9, in <module>
    a.x="ZSP"
AttributeError: can't set attribute
}}}

=== isinstance( object, classinfo) ===
判断一个对象是否是一个类的实例
{{{
>>>class A:pass

>>>class B:pass

>>>a=A()

>>>isinstance(a,A)
True

>>>isinstance(a,B)
Line 1810: Line 1083:



>>>Decimal('1.00')%Decimal('.10')

Decimal("0.00")



>>> 1.00%0.10

0.09999999999999995



getcontext().prec=36

>>>print Decimal(1)/Decimal(7)

0.142857142857142857142857142857142857

----------------------------------------------------------

 

= 反馈 =
}}}
<<Include(PyCommonUsageMod)>>

Python 绝对简明手册 -- [email protected] ::-- ZoomQuiet [2006-09-15 04:35:33]

简述

1. 阅读须知

文中使用

>>>

作为会命令行中的输出信息的前缀

对于不清楚用用途的函数可以在解释器下面输入

help(函数名)

来获取相关信息

另外,自带的文档和google也是不可少的

2. 基本语法

2.1. if / elif / else

x=int(raw_input("Please enter an integer:"))#获取行输入

if x>0:
    print '正数'
elif x==0:
    print '零'
else:
    print '负数'

此外C语言中类似"xxx?xxx:xxx"在Python中可以这样写

>>>number=8
>>>print "good" if 8==number else "bad" #当满足if条件时返回"good",否则返回"bad"
good

2.2. in

in判断 一个数 是否在 一个集合(如:元组,列表等) 中

if 'yes' in  ('y','ye','yes'):print  'ok'

2.3. for ... in

python中没有类似C中的for循环,而是使用for...in来对集合中的每一个元素进行操作

a=['cat','door','example']
for x in a:
    print x

如果要修改a的内容,请用a的副本循环(否则不安全),如:

a=["cat","[email protected]"]
for x in a[:]:
    if len(x)>6:a.insert(0,x)
>>>a
['[email protected]', 'cat', '[email protected]']

若需要得到循环的次数,参见 函数 range 的用法

2.4. break / continue

这两个的用法和C中相同

for i in range(10):
    if 2==i:continue #结束当前循环,进入下一步循环
    if 6==i:break #跳出循环
    print i

输出

0
1
3
4
5

2.5. while / pass

while True:
    pass #什么也不做

2.6. is

用来比较两个变量是否指向同一内存地址(也就是两个变量是否等价) 而 == 是用来比较两个变量是否逻辑相等

a=[1,2]
b=[1,2]
>>> a is b
False
>>> a == b
True

2.7. del

用于删除元素

a=[1,2,3,4,5,6]

del a[0]
a
>>>[2,3,4,5,6]

del a[2:4]
a
>>>[2,3,6]

del a[:]
a
>>>[]

del a
a
#抛出异常
>>>NameError: name 'a' is not defined

2.8. try ... except ... finally / raise

try ... except用于异常处理

try:
    x=int(raw_input("请输入数字:"))
except ValueError: #可以同时捕获多个异常,写法如except(RuntimeError,ValueError):
    #当输入非数字时
    print"您输入不是数字"
except: #省略异常名,可以匹配所有异常,慎用
    pass
else:#当没有异常时
    print 'result=',result
finally:#和Java中类似。一般用于释放资源,如文件,网络连接。
   print 'finish'

raise用于抛出异常,可以为自定义的异常类

惯例是以Error结尾的类,同类的异常一般派生自同一个基类(如Exception)

class MyError(Exception):
    def __init__(self,value):
        self.value=value
    def __str__(self):
        return reper(self.value)

基类异常可以匹配派生类异常

try:
    raise Exception("spam","egg")
except Exception,inst:#inst为该异常类的实例,为可选项
    print type(inst) #异常的类型
    print inst

3. 内建类型

3.1. None

None 表示该值不存在,比如 没有定义返回值 的函数就 返回None

3.2. Ture / False

布尔类型,Ture等价于1,False等价于0

3.3. List

>>>test=[1,2,"yes"]

3.3.1. 内建函数

append(x) 追加到链尾

extend(L) 追加一个列表,等价于+=

insert(i,x) 在位置i插入x

remove(x) 删除第一个值为x的元素,如果不存在会抛出异常

reverse() 反转序列

pop([i]) 返回并删除位置为i的元素,i默认为最后一个元素(i两边的[]表示i为可选的,实际不用输入)

index(x) 返回第一个值为x的元素,不存在则抛出异常

count(x) 返回x出现的次数

sort() 排序

例子:

>>>test=[1,2,"yes"]

>>>test.append(1) #追加到链尾
>>>test
[1, 2, 'yes', 1]

>>>test.extend([ 'no','maybe']) #追加一个列表
>>>test
[1, 2, 'yes', 1, 'no', 'maybe']

>>> test.insert(0,'never') #在位置0插入'never'
>>> test
['never', 1, 2, 'yes', 1, 'no', 'maybe']

>>> test.remove('no') #删除第一个值为"no"的元素,如果不存在会抛出异常
>>> test
['never', 1, 2, 'yes', 1, 'maybe']

>>> test.reverse() #反转序列
>>> test
['maybe', 1, 'yes', 2, 1, 'never']

>>> test.pop() #返回并删除位置为i的元素,i默认为最后一个元素
'never'
>>> test
['maybe', 1, 'yes', 2, 1]

>>> test.index('yes') #返回第一个值为'yes'的元素,不存在则抛出异常
2

>>> test.count(1) #返回1出现的次数
2

>>>test.sort() #排序
>>> test
[1, 1, 2, 'maybe', 'yes']

3.3.2. 切片

从序列中抽取一部分

>>> test=['never', 1, 2, 'yes', 1, 'no', 'maybe']

>>> test[0:3] #包括test[0],不包括test[3]
['never', 1, 2]

>>> test[0:6:2] #包括test[0],不包括test[6],而且步长为2
['never', 2, 1]

>>> test[:-1] #包括开始,不包括最后一个
['never', 1, 2, 'yes', 1, 'no']

>>> test[-3:] #抽取最后3个
[1, 'no', 'maybe']

>>>test[::-1] #倒序排列
['maybe', 'no', 1, 'yes', 2, 1, 'never']

3.3.3. 列表推导式

可以直接通过for循环生成一个list

>>>freshfruit=['  banana  ','   loganberry  ']
>>>[weapon.strip() for weapon in freshfruit]
['banana', 'loganberry']

说明:strip()是去除字符串两端多于空格,该句是去除序列中的所有字串两端多余的空格

>>>vec=[2,4,6]
>>>[3*x for x in vec if x>3]
[12, 18]

>>>[(x,x**2) for x in vec]
#循环变量要是一个sequence,而[x,x**2 for x in vec]是错误的
[(2,4),(4,16),(6,36)]

>>>vec2=[4,3,-9]

>>>[x*y for x in vec for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]

>>>[vec[i]+vec2[i] for i in range(len(vec))]
[6, 7, -3]

>>>[str(round(355/113.0,i)) for i in range(1,6)]
#str()是转换类型为可以打印的字符
#round(x,n)表示对x保留n位小数(四舍五入)
['3.1', '3.14', '3.142', '3.1416', '3.14159']

3.4. 元组

一旦初始化便不能更改的数据结构,速度比list快

>>>t=1234,5567,'hello' #t=(1234,5567,'hello')的简写

>>>x,y,z=t    #拆分操作可以应用于所有sequence
>>>x
1234

>>>u=t,(1,2,3)
>>>u
((1234,5567,'hello'),(1,2,3))

>>>empty=() #空元组
>>>singleton='hi', #单个元素的元组,注意逗号

通过元组可以很简单的进行数据交换. 比如:

a=1
b=2
a,b=b,a

3.5. set

set(集合):无序不重复的元素集

>>>basket = ['apple','orange','apple','pear','apple','banana']

>>>fruit=set(basket)

>>>fruit
set(['orange', 'pear', 'apple', 'banana'])

>>>'orange' in fruit
True

>>>a=set('abracadabew')
>>>a
set(['a', 'c', 'b', 'e', 'd', 'r', 'w'])

>>>b=set('wajgwaoihwb')
>>>b
set(['a', 'b', 'g', 'i', 'h', 'j', 'o', 'w'])
 
>>>a-b    #差
set(['c', 'r', 'e', 'd'])

>>>a|b   #并
set(['a', 'c', 'b', 'e', 'd', 'g', 'i', 'h', 'j', 'o', 'r', 'w'])

>>>a&b   #交
set(['a', 'b', 'w'])

>>>a^b   #(并-交)
set(['c', 'e', 'd', 'g', 'i', 'h', 'j', 'o', 'r'])

3.6. dict

字典:关键字为不可变类型,如字符串,整数,只包含不可变对象的元组.

列表等不可以作为关键字.

如果列表中存在关键字对,可以用dict()直接构造字典.而这样的列表对通常是由列表推导式生成的.

>>>tel={'jack':4098,'sape':4139}

>>>tel['guido']=4127

>>>tel
{'sape': 4139, 'jack': 4098, 'guido': 4127}

>>>tel['jack'] #如果jack不存在,会抛出KeyError
4098
>>>a.get("zsp",5000) #如果"zsp"为tel的键则返回其值,否则返回5000

>>>del tel['sape'] #删除键'sape'和其对应的值
>>>tel.keys() #复制一份键的副本,同理tel.items()为值的副本
['jack', 'guido']

>>>"jack" in tel #判断"jack"是否tel的键
True
>>>"zsp" not in tel
True

>>>for k,v in tel.iteritems():print k,v  #同理tel.iterkeys()为键的迭代器,tel.itervalues()为值的迭代器
jack 4098
guido 4127

>>>tel.copy() #复制一份tel
{'jack': 4098, 'guido': 4127}

>>> tel.fromkeys([1,2],0) #从序列生成并返回一个字典,其值为第二个参数(默认为None),不改变当前字典
{1: 0, 2: 0}

>>>tel.popitem() #弹出一项
('jack', 4098)

4. 函数相关

4.1. 函数定义 / 参数默认值

def fib(n=2,a=1):#参数可以有默认值
    """这里给函数写文档注释"""
    for i in range(n):
        print a


>>>f=fib #可以用一个变量表示函数
>>>f(3)
1
1
1

>>>fib(a=2) #多个可选参数赋值可以直接写"参数变量名=值"来快速赋值
2
2

4.2. Lambda函数

一种无名函数的速写法

def make_incrementor(n):
    return lambda x: x+n

f=make_incrementor(n)
#f等价于
#def f(x):
#       return x+n

4.3. 不定长参数 *para,**para

参数格式为 *para 表示接受一个元组

为 **para 表示接受一个字典

*para要在**para之前

def test(*args,**dic):
    for arg in args :
        print arg
    for k,v in dic.iteritems():
        print k ,':',v

>>> test("yes",1,2,me="张沈鹏",where="中国") #"yes",1,2传递给元组;me="张沈鹏",where="中国"传递给字典
yes
1
2
me : 张沈鹏
where : 中国

4.4. @ 装饰器

@A def B:pass 等价于 def B:pass B=A(B) 即将函数B作为参数传给参数A

from time import time
#测试运行时间
def cost_time(func):
    def result(*args,**dic):
        beign=time()
        func(*args,**dic)
        print "cost time : ",time()-beign
    return result

@cost_time
def show(n):
    for x in range(n):print x

>>> show(10)
0
1
2
3
4
5
6
7
8
9
cost time :  0.0469999313354

4.5. 生成器表达式

生成器表达式:类似于没有中括号的列表推导式,可用在参数中

>>>sum(i*i for i in range(10))
285

>>>unique_words=set(word for line in page for word in line.split())#page为打开的文件

>>>data='golf'

>>>list(data[i] for i in range(len (data)-1,-1,-1))
['f','l','o','g']

4.6. yield

每次调用返回一个值,并记录当前执行位置所有的变量

def reverse(data):
    for index in range(len(data)-1,-1,-1):
        yield data[index]

for char in reverse("golf"):
    print char,

输出

f l o g

5. 常用函数

5.1. eval

对字符串参数运算,求值

>>> eval("1 + 2*3") #可以方便的用来做四则运算
7
>>> a=1
>>> eval('a+1') #可以访问变量
2

5.2. exec

将字符串参数作为python脚本执行

>>> exec('a="Zsp"')
>>> a
'Zsp'

5.3. execfile

和exec类似,不过是用来打开一个文件,并作为python脚本执行

5.4. dir

显示对象的所有属性(即可以用"."操作直接访问)

>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

5.5. help

help(类/函数) 返回相应对象的文档字符串

>>> help(vars)
Help on built-in function vars in module __builtin__:

vars(...)
    vars([object]) -> dictionary
    
    Without arguments, equivalent to locals().
    With an argument, equivalent to object.__dict__.

5.6. len

返回序列/字典的长度

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

5.7. print

输出字符串 用法演示:

print "Today ", #加逗号,输出后不换行

name="ZSP"

print name,"cost $",10 #输出多个变量

print "hello,%s!"%name #%s 表示用str转化为字符串

for x in xrange(1,11):
    print '%2d %3d' % (x,x*x) #小数输出如   %5.3f

对于字典可以用变量名来直接格式化,如:

>>>table={'Sjoerd':4127,'Jack':4098,'Dcab':8637678}
>>>print 'Jack:%(Jack)d; Sjoerd:%(Sjoerd)d; Dcab:%(Dcab)d' %
table
Jack:4098; Sjoerd:4127; Dcab:8637678

同时,函数vars()返回包含所有变量的字典,配合使用,无坚不摧!

5.8. raw_input

x=raw_input("Please enter an sentence:") #将输入的内容赋值给x

5.9. range

range(10,0,-3)#参数的含义为起点(默认为0),终点(不含终点),步长(默认为1)
>>>[10,7,4,1]

和for...in配合使用

a=['cat','door','example']
for i in range(len(a)):#len()函数为求序列的长度
    print i,a[i]

5.10. filter

filter(function , sequence) 返回序列,为原序列中能使function返回true的值

>>>a=[1,2,3,4]
>>>filter(lambda x:x%2,a)
[1, 3]

5.11. map

map(function,sequence,[sequence...])

返回序列,为对原序列每个元素分别调用function获得的值.

可以传入多个序列,但function也要有相应多的参数,如

map(lambda x,y,z:x+y+z,range(1,3),range(3,5),range(5,7))

计算过程为

1+3+5=9

2+4+6=12

返回[9,12]

5.12. reduce

reduce(function,sequence,[init])

返回一个单值为,计算步骤为 :

  • 第1个结果=function(sequence[0],sequence[1])
  • 第2个结果=function(第1个结果,sequence[2])
  • 返回最后一个计算得值
  • 如果有init,则先调用function(init,sequence[0]) 

  • sequence只有一个元素时,返回该元素,为空时抛出异常.

reduce(lambda x,y:x+y,range(3),99) 的计算为

99+0=99 => 99+1=100 => 100+2=102

返回102

注:实际使用中用内建函数sum来完成这个累加更合适,如这里等价sum(range(3),99)

5.13. zip

zip用于多个sequence的循环

questions=['name','quest','favorite color']
answers=['lancelot','the holy grail','blue']

for q,a in zip(questions,answers):
    print 'What is your %s ? It is %s.'%(q,a)

输出:

What is your name ? It is lancelot.
What is your quest ? It is the holy grail.
What is your favorite color ? It is blue.

5.14. reversed反向循环

for i in reversed(range(1,4)):
    print i

输出:

3
2
1

5.15. sorted排序

返回一个有序的新序列

>>>sorted([2,5,1,4])
[1, 2, 4, 5]

5.16. enumerate 返回索引位置和对应的值

for i,v in enumerate(['tic','tac','toe'])
    print i,v

输出:

0 tic
1 tac
2 toe

5.17. open/文件操作

f=open('/tmp/hello','w')

#open(路径+文件名,读写模式)

#读写模式:r只读,r+读写,w新建(会覆盖原有文件),a追加,b二进制文件.常用模式

如:'rb','wb','r+b'等等

f.read([size]) size未指定则返回整个文件,如果文件大小>2倍内存则有问题.f.read()读到文件尾时返回""(空字串)

file.readline() 返回一行

file.readline([size]) 返回包含size行的列表,size 未指定则返回全部行

for line in f: print line #通过迭代器访问

f.write("hello\n") #如果要写入字符串以外的数据,先将他转换为字符串.

f.tell() 返回一个整数,表示当前文件指针的位置(就是到文件头的比特数).

f.seek(偏移量,[起始位置])

用来移动文件指针

偏移量:单位:比特,可正可负

起始位置:0-文件头,默认值;1-当前位置;2-文件尾

f.close() 关闭文件

6. 模块化

6.1. 导入模块

模块的查找路径

1.当前的目录

2.环境变量PYTHONPATH所指的目录列表

3.python解释器的安装目录

如将代码保存上述的一个目录中的的fibo.py文件中,便可以

import fibo
fibo.function()

如果想直接使用fibo.function可以重命名这个函数,如

f=fibo.function
f()

也可以

form fibo import function
function()

甚至可以form fibo import * 

可以 form 包.子包.模块 imort 函数 

然后就直接使用该函数,不需要加前缀

6.2. 包

引用推荐写法为

form 包 import 模块

几个功能类似的模块可以组合成一个包,

比如一个可以处理.wav,.mp3,.wma等音频文件的有类似如下结构:

Sound/
        __init__.py
        Formats/
                __init__.py
                wavread.py
                wavwrite.py
                mp3read.py
                mp3write.py
                wmaread.py
                wmawrite.py
        Effects/
                __init__.py
                echo.py
                surround.py
                reverse.py

只有当init.py存在时python才将该文件夹视为一个包.

该文件可以为空文件 一般在init.py文件中定义一个all列表,包含要import *时要导入的模块. 如Sound/Effects/init.py可以有如下内容

__all__=["echo","surround","reverse"]

包的作者在发布包时可以更新这个列表,也可以根据需要让某个模块不支持import *

对于包中同一个文件夹下的模块可以把

form 包.子包 imort 模块

简写为 imort 模块

6.3. 面向对象

6.3.1. 概要

class ClassName:
    "类文档,可以通过类名.__doc__访问"
    def f(self):#self为每个类函数的必要的一个参数,可以通过它来访问当前实例
        return self.content

    def __init__(self,word=''):#构造函数
        #构造函数,可以初始化变量,可以有参数"
        self.content=word
        self.__name=word #私有变量,以"__"开头,不以"__"结尾的变量

创建类实例 x=ClassName("good")

6.3.2. 类继承

class DerivedClassName(BassClassName):

  • pass

如果基类定义在另一个模块中, 要写成

modname.BaseClassName

派生类的函数会覆盖基类的同名函数

如果想扩充而不是改写基类的函数,可以这样调用基类函数

BaseClassName.methodname(self,arguments)

注意:该基类要在当前全局域或被导入

class A:
    def hi(self):
        print "A"
class B:
    def hi(self):
        A.hi(self)
        super(B).hi() #通过super关键字可以获得当前类的基类
        print "B"

B().hi()

输出

A
B

6.3.3. 多重继承

类多继承

class DerivedClassName(Base1,Base2,Base3):
    pass

对于该类函数的解析规则是深度优先,先是Base1,然后是Base1的基类,诸如此类.

class A:
    def hi(self):
        print "A"

class B:
    def hi(self):
        print "B"
        
class C(A,B):
    pass

C().hi()

输出:

A

6.4. 操作符重载

通过定义类的一些约定的以""开头并结尾的函数,可以到达重载一些特定操作的目的,下面是是一些常用的重载

6.4.1. __str__ / __unicode__

当print一个对象实例时,实际是print该实例str()函数的返回值.

class A:
    def __str__(self):
        return "A"
    def __unicode__(self):
        return "uA"

print A()
print unicode(A())

输出

A
uA

unicodestr类似,不过返回Unicode字符串.

6.4.2. 比较操作

x<y x.lt(y)

x<=y x.le(y)

x==y x.eq(y)

x!=y 或 x<>y x.ne(y)

x>y x.gt(y)

x>=y x.ge(y)

cmp( self, other) 用来简化比较函数的定义 self < other返回负数,相等时返回0,self>other时返回正数

class A:
    def __init__(self,i):
        self.i=i
    def __cmp__(self,other):
        return self.i-other.i

print A(1)>A(2)

输出

False

6.4.3. __iter__

for ... in 循环即就是通过这个函数遍历当前容器的对象实例 可配合yield方便的编写这个函数(参见基本语法yield)

class A:
   def __init__(self,n):
       self.n=n
   def __iter__(self):
       n=self.n
       while n:
           m=n%2
           n/=2
           yield m

for i in A(5):
    print i,

输出

1 0 1 

另有一种繁琐的实现: 返回一个可以通过next()函数遍历的对象,当结束时抛出StopIteration异常

6.5. 类相关函数

6.5.1. type

返回对象的类型

>>> type("")
<type 'str'>
>>> type("")==str
True

>>> type([])
<type 'list'>
>>> type([])==list
True

>>> type({})
<type 'dict'>

>>> type(())
<type 'tuple'>

>>> class A:pass

>>> type(A)
<type 'classobj'>

>>> type(A())
<type 'instance'>

>>> import types #在types模块中有许多类型的定义

>>> type(A)==types.ClassType
True

6.5.2. getattr / hasattr /delattr

getattr:通过类实例和一个字符串动态的调用类函数/属性

class A:
    def name(self):
        return "ZSP"
    def hello(self):
        return "nice to meet me ."

def say(obj,attr):
    print getattr(obj,attr)()

a=A()
say(a,"name")
say(a,"hello")

输出

ZSP
nice to meet me .

hasattr 用来判断实例有无该函数/属性

delattr 用来删除实例的函数/属性

6.5.3. property

通过值的方式调用实例无参函数

class A(object):
    def __init__(self): self._x = None
    def getx(self): return self._x
    def setx(self, value): self._x = value
    def delx(self): self._x=None
    x = property(getx, setx, delx, "I'm the 'x' property.")
a=A()
print a.x

a.x="ZSP"
print a.x

del a.x
print a.x

输出

None
ZSP
None

可以方便的定义一个只读属性

class A(object):
    @property
    def x(self): return "Property"

调用

>>>a=A()

>>>print a.x
Property

>>>a.x="ZSP" #只读属性,不能更改
Traceback (most recent call last):
  File "D:\Profile\Untitled 2.py", line 9, in <module>
    a.x="ZSP"
AttributeError: can't set attribute

6.5.4. isinstance( object, classinfo)

判断一个对象是否是一个类的实例

>>>class A:pass

>>>class B:pass

>>>a=A()

>>>isinstance(a,A)
True

>>>isinstance(a,B)
False

Python 常用模块体验 ::-- ZoomQuiet [2007-11-10 06:37:48]

CPUG联盟::

CPUG::门户plone

BPUG

SPUG

ZPUG

SpreadPython Python宣传

7. Py常用模块汇编

'Python 标准库2.0 整理者

Python 江湖 QQ 群: 43680167
Feather (校对) gt: [email protected]

一些有用的Python函式庫列表 » 程式設計 遇上 小提琴

::-- ZoomQuiet [2007-11-10 07:39:01]

CPUG联盟::

CPUG::门户plone

BPUG

SPUG

ZPUG

SpreadPython Python宣传

7.1. zshelve 对象持久模块

{{{Jiahua Huang <[email protected]> reply-to [email protected], to "python. cn" <[email protected]>, date Nov 8, 2007 5:41 PM subject [CPyUG:34726] 贴个 zlib 压缩的 zshelve 对象持久模块 }}} 这个给 Python 标准库的 shelve.py 添加了 zlib 压缩, 减小数据库文件体积,以改善磁盘 io 性能

7.1.1. 发布

http://zshelve.googlecode.com/svn/trunk/

加了个命令行工具:

huahua@huahua:tmp$ zshelve
commandline tool for zshelve databases

Usage: zshelve  FILE  dump                    Dump the data tree
      zshelve  FILE  keys                    List of keys
      zshelve  FILE  get          KEY        Dump value for key
      zshelve  FILE  set          KEY VALUE  Set db[key] = value
      zshelve  FILE  has_key      KEY        True if database has the key
      zshelve  FILE  search_key   KEY        Search key
      zshelve  FILE  search_value VALUE      Search value

huahua@huahua:tmp$ zshelve set tes.db a 1
huahua@huahua:tmp$ zshelve dump tes.db
   |- a
   |    | - 1
huahua@huahua:tmp$ zshelve set tes.db b "dict(a=1,b=2,c=3,d={'s':'4'})"
huahua@huahua:tmp$ zshelve dump tes.db
   |- a
   |    |- 1
   |- b
   |    |- a
   |    |    |- 1
   |    |- c
   |    |    |- 3
   |    |- b
   |    |    |- 2
   |    |- d
   |    |    |- s
   |    |    |    |- 4

对比::

>>> import zshelve
>>> import shelve
>>> zdb = zshelve.open('/tmp/zshelve.db')
>>> db  = shelve.open('/tmp/shelve.db')
>>> zdb['1'] = dict(a='0123456789'*10000000)
>>> db['1']  = dict(a='0123456789'*10000000)
>>> zdb.sync()
>>> db.sync()

看看文件大小差异::

huahua@huahua:zshelve$ ll /tmp/*shelve.db
-rw-r--r-- 1 huahua huahua  96M 2007-11-08 17:36 /tmp/shelve.db
-rw-r--r-- 1 huahua huahua 204K 2007-11-08 17:36 /tmp/zshelve.db

7.1.2. 补丁::

--- shelve.py   2007-05-03 00:56:36.000000000 +0800
+++ zshelve.py  2007-11-08 17:25:59.000000000 +0800
@@ -70,6 +70,7 @@ except ImportError:

 import UserDict
 import warnings
+import zlib        ## use zlib to compress dbfile

 __all__ = ["Shelf","BsdDbShelf","DbfilenameShelf","open"]

@@ -80,13 +81,14 @@ class Shelf(UserDict.DictMixin):
    See the module's __doc__ string for an overview of the interface.
    """

-    def __init__(self, dict, protocol=None, writeback=False):
+    def __init__(self, dict, protocol=None, writeback=False, compresslevel=2):
        self.dict = dict
        if protocol is None:
             protocol = 0
        self._protocol = protocol
        self.writeback = writeback
        self.cache = {}
+        self.compresslevel = compresslevel

    def keys(self):
        return self.dict.keys()
@@ -109,7 +111,7 @@ class Shelf(UserDict.DictMixin):
        try:
            value = self.cache[key]
        except KeyError:
-            f = StringIO(self.dict[key])
+            f = StringIO(zlib.decompress(self.dict[key]))
            value = Unpickler(f).load()
            if self.writeback:
                self.cache[key] = value
@@ -121,7 +123,7 @@ class Shelf(UserDict.DictMixin):
        f = StringIO()
        p = Pickler(f, self._protocol)
        p.dump(value)
-        self.dict[key] = f.getvalue()
+        self.dict[key] = zlib.compress(f.getvalue(), self.compresslevel)

    def __delitem__(self, key):
        del self.dict[key]
@@ -168,32 +170,32 @@ class BsdDbShelf(Shelf):
    See the module's __doc__ string for an overview of the interface.
    """

-    def __init__(self, dict, protocol=None, writeback=False):
-        Shelf.__init__(self, dict, protocol, writeback)
+    def __init__(self, dict, protocol=None, writeback=False, compresslevel=2):
+        Shelf.__init__(self, dict, protocol, writeback, compresslevel)

    def set_location(self, key):
        (key, value) = self.dict.set_location(key)
-        f = StringIO(value)
+        f = StringIO(zlib.decompress(value))
        return (key, Unpickler(f).load())

    def next(self):
        (key, value) = self.dict.next()
-        f = StringIO(value)
+        f = StringIO(zlib.decompress(value))
        return (key, Unpickler(f).load())

    def previous(self):
        (key, value) = self.dict.previous()
-        f = StringIO(value)
+        f = StringIO(zlib.decompress(value))
        return (key, Unpickler(f).load())

    def first(self):
        (key, value) = self.dict.first()
-        f = StringIO(value)
+        f = StringIO(zlib.decompress(value))
        return (key, Unpickler(f).load())

    def last(self):
        (key, value) = self.dict.last()
-        f = StringIO(value)
+        f = StringIO(zlib.decompress(value))
        return (key, Unpickler(f).load())


@@ -204,12 +206,12 @@ class DbfilenameShelf(Shelf):
    See the module's __doc__ string for an overview of the interface.
    """

-    def __init__(self, filename, flag='c', protocol=None, writeback=False):
+    def __init__(self, filename, flag='c', protocol=None,
writeback=False, compresslevel=2):
        import anydbm
-        Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback)
+        Shelf.__init__(self, anydbm.open(filename, flag), protocol,
writeback, compresslevel)


-def open(filename, flag='c', protocol=None, writeback=False):
+def open(filename, flag='c', protocol=None, writeback=False, compresslevel=2):
    """Open a persistent dictionary for reading and writing.

    The filename parameter is the base filename for the underlying
@@ -222,4 +224,4 @@ def open(filename, flag='c', protocol=No
    See the module's __doc__ string for an overview of the interface.
    """

-    return DbfilenameShelf(filename, flag, protocol, writeback)
+    return DbfilenameShelf(filename, flag, protocol, writeback, compresslevel)

::-- ZoomQuiet [2007-11-10 07:34:49]

Contents

  1. fast UserDict

7.2. fast UserDict

{{{Jiahua Huang <[email protected]> reply-to [email protected], to "python. cn" <[email protected]>, date Nov 10, 2007 3:28 PM subject [CPyUG:34791] 一行代码让 UserDict.UserDict 的类加速 4 倍 }}} 发现 Python 标准库里好些字典类从 UserDict.UserDict 派生, 而不是从 dict 派生, 是因为 旧版 python 内建类型不能派生子类,

那么这会不会影响速度呢,

先给两个分别继承 UserDict.UserDict 和 dict 的类 URdict, Rdict

>>> import UserDict
>>> class URdict(UserDict.UserDict):
...     '''dict can search key by value
...     '''
...     def indexkey4value(self, value):
...         '''search key by value
...         >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
...         >>> rd.indexkey4value('Other')
...         'b'
...         '''
...         try:
...             ind = self.values().index(value)
...             return self.keys()[ind]
...         except:
...             return None
...     def key4value(self, svalue):
...         '''search key by value
...         >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
...         >>> rd.key4value('Other')
...         'b'
...         '''
...         for key, value in self.iteritems():
...             if value == svalue:
...                 return key
...     def keys4value(self, svalue):
...         '''search keys by value
...         >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
...         >>> rd.keys4value('Other')
...         ['b', 'e']
...         '''
...         keys=[]
...         for key, value in self.iteritems():
...             if value == svalue:
...                 keys.append(key)
...         return keys
...
>>>
>>> class Rdict(dict):
...     '''dict can search key by value
...     '''
...     def indexkey4value(self, value):
...         '''search key by value
...         >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
...         >>> rd.indexkey4value('Other')
...         'b'
...         '''
...         try:
...             ind = self.values().index(value)
...             return self.keys()[ind]
...         except:
...             return None
...     def key4value(self, svalue):
...         '''search key by value
...         >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
...         >>> rd.key4value('Other')
...         'b'
...         '''
...         for key, value in self.iteritems():
...             if value == svalue:
...                 return key
...     def keys4value(self, svalue):
...         '''search keys by value
...         >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
...         >>> rd.keys4value('Other')
...         ['b', 'e']
...         '''
...         keys=[]
...         for key, value in self.iteritems():
...             if value == svalue:
...                 keys.append(key)
...         return keys
...
>>>

>>> import time
>>> def _timeit(_src):
...     exec('''
... _t0 = time.time()
... %s
... _t1 = time.time()
... _t3 = _t1 - _t0
... '''%_src)
...     return _t3
...
>>> ran = range(100000)

再弄俩实例
>>> u = URdict()
>>> r = Rdict()

看看插入速度
>>> _timeit("for i in ran: u[i]=i")
0.1777961254119873
>>> _timeit("for i in ran: r[i]=i")
0.048948049545288086

看看原始 dict 的速度
>>> _timeit("for i in ran: d[i]=i")
0.041368961334228516

可以看到, UserDict.UserDict 确实严重影响速度,

python 标准库里边好多 UserDict 的都应该换成 dict , 以提高性能

不过,一个个修改 Python 标准库似乎又不合适,

再次使用一招鲜,直接干掉 UserDict

在使用/导入那些模块前先来一行

>>> import UserDict; UserDict.UserDict = dict

完了再导入模块来试试

>>> u = URdict()
>>> _timeit("for i in ran: u[i]=i")
0.042366981506347656

一行代码让速度提高 4 倍

PyAbsolutelyZipManual (last edited 2009-12-25 07:09:10 by localhost)