PYTHON基础(转)

来源:互联网 发布:手机后期ps软件 编辑:程序博客网 时间:2024/05/01 11:17
2. 基本语法

2.1. if / elif / else

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

 

if x>0:

    print'正数'

elif x==0:

    print'零'

else:

    print'负数'

 

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

 

>>>number=8

>>>print "good" if8==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","zsp007@gmail.com"]

for x in a[:]:

    iflen(x)>6:a.insert(0,x)

>>>a

['zsp007@gmail.com', 'cat', 'zsp007@gmail.com']

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

 

2.4. break / continue

这两个的用法和C中相同

for i in range(10):

    if2==i:continue #结束当前循环,进入下一步循环

    if6==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]

>>> ais 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:

    raiseException("spam","egg")

except Exception,inst:#inst为该异常类的实例,为可选项

    printtype(inst) #异常的类型

    printinst

 

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() forweapon in freshfruit]

['banana', 'loganberry']

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

>>>vec=[2,4,6]

>>>[3*x for x in vecif x>3]

[12, 18]

>>>[(x,x**2) for x invec]

#循环变量要是一个sequence,而[x,x**2 for x in vec]是错误的

[(2,4),(4,16),(6,36)]

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

 

>>>[x*y for x in vecfor y in vec2]

[8, 6, -18, 16, 12, -36, 24, 18, -54]

 

>>>[vec[i]+vec2[i] fori 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' infruit

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

 

>>>deltel['sape'] #删除键'sape'和其对应的值

>>>tel.keys()#复制一份键的副本,同理tel.items()为值的副本

['jack', 'guido']

 

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

True

>>>"zsp" not intel

True

 

>>>fork,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 inrange(n):

       print a

 

 

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

>>>f(3)

1

1

1

 

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

2

2

 

4.2. Lambda函数

一种无名函数的速写法

def make_incrementor(n):

    returnlambda 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 inargs :

       print arg

    for k,v indic.iteritems():

       print k ,':',v

 

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

yes

1

2

me : 张沈鹏

where : 中国

 

4.4. @ 装饰器

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

from time import time

#测试运行时间

def cost_time(func):

    defresult(*args,**dic):

       beign=time()

       func(*args,**dic)

       print "cost time : ",time()-beign

    returnresult

 

@cost_time

def show(n):

    for x inrange(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 inrange(10))

285

 

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

 

>>>data='golf'

 

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

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

 

4.6. yield

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

def reverse(data):

    for index inrange(len(data)-1,-1,-1):

       yield data[index]

 

for char in reverse("golf"):

    printchar,

输出

f l o g

 

5. 常用函数

5.1. eval

对字符串参数运算,求值

>>>eval_r("1 + 2*3") #可以方便的用来做四则运算

7

>>>a=1

>>>eval_r('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

   

    Withoutarguments, equivalent to locals().

    With anargument, 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 '- ='% (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()函数为求序列的长度

    printi,a[i]

 

5.10. filter

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

>>>a=[1,2,3,4]

>>>filter(lambdax:x%2,a)

[1, 3]

 

5.11. map

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

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

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

map(lambdax,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 'Whatis 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'])

    printi,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__访问"

    deff(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:

    defhi(self):

       print "A"

class B:

    defhi(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:

    defhi(self):

       print "A"

 

class B:

    defhi(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<=y x.le(y)

x==y x.eq(y)

x!=y 或 x<>yx.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

True

 

>>>type([])

 

>>>type([])==list

True

 

>>>type({})

 

 

>>>type(())

 

 

>>>class A:pass

 

>>>type(A)

 

 

>>>type(A())

 

 

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

 

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

True

 

6.5.2. getattr / hasattr /delattr

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

class A:

    defname(self):

       return "ZSP"

    defhello(self):

       return "nice to meet me ."

 

def say(obj,attr):

    printgetattr(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

    defgetx(self): return self._x

    defsetx(self, value): self._x = value

    defdelx(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

   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-1006:37:48]

目录

1.    Py常用模块汇编

1.    zshelve 对象持久模块

1.    发布

2.    补丁::

2.    fast UserDict

 

7. Py常用模块汇编

'Python标准库2.0 整理者

Python 江湖 QQ 群: 43680167

Feather (校对) gt: andelf@gmail.com

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

::-- ZoomQuiet [2007-11-1007:39:01]

 

7.1. zshelve 对象持久模块

{{{Jiahua Huang <<Ahref="mailto:jhuangjiahua@gmail.com">jhuangjiahua@gmail.com> reply-to python-cn@googlegroups.com, to"python. cn" <<Ahref="mailto:python-cn@googlegroups.com">python-cn@googlegroups.com>, dateNov 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         KEYVALUE  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_valueVALUE     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  96M2007-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-0817:25:59.000000000 +0800

@@ -70,6 +70,7 @@ except ImportError:

 

 import UserDict

 import warnings

+importzlib       ## use zlib to compress dbfile

 

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

 

@@ -80,13 +81,14 @@ classShelf(UserDict.DictMixin):

    See themodule'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

 

    defkeys(self):

       return self.dict.keys()

@@ -109,7 +111,7 @@ classShelf(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 @@ classShelf(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 themodule'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)

 

    defset_location(self, key):

       (key, value) = self.dict.set_location(key)

      f = StringIO(value)

      f = StringIO(zlib.decompress(value))

       return (key, Unpickler(f).load())

 

    defnext(self):

       (key, value) = self.dict.next()

      f = StringIO(value)

      f = StringIO(zlib.decompress(value))

       return (key, Unpickler(f).load())

 

    defprevious(self):

       (key, value) = self.dict.previous()

      f = StringIO(value)

      f = StringIO(zlib.decompress(value))

       return (key, Unpickler(f).load())

 

    deffirst(self):

       (key, value) = self.dict.first()

      f = StringIO(value)

      f = StringIO(zlib.decompress(value))

       return (key, Unpickler(f).load())

 

    deflast(self):

       (key, value) = self.dict.last()

      f = StringIO(value)

      f = StringIO(zlib.decompress(value))

       return (key, Unpickler(f).load())

 

 

@@ -204,12 +206,12 @@ classDbfilenameShelf(Shelf):

    See themodule'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 apersistent dictionary for reading and writing.

 

    The filenameparameter is the base filename for the underlying

@@ -222,4 +224,4 @@ def open(filename, flag='c',protocol=No

    See themodule's __doc__ string for an overview of the interface.

    """

 

   returnDbfilenameShelf(filename, flag, protocol, writeback)

   returnDbfilenameShelf(filename, flag, protocol, writeback,compresslevel)

  • 一行代码让 UserDict.UserDict 的类加速4 倍

::-- ZoomQuiet [2007-11-1007:34:49]

 

目录

1.    fast UserDict

7.2. fast UserDict

{{{Jiahua Huang <<Ahref="mailto:jhuangjiahua@gmail.com">jhuangjiahua@gmail.com> reply-to python-cn@googlegroups.com, to"python. cn" <<Ahref="mailto:python-cn@googlegroups.com">python-cn@googlegroups.com>, dateNov 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:

...                returnkey

...    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

0 0
原创粉丝点击