设为首页 收藏本站
查看: 836|回复: 0

[经验分享] Python 绝对简明手册

[复制链接]

尚未签到

发表于 2015-4-22 09:14:41 | 显示全部楼层 |阅读模式
  简述  
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","zsp007@gmail.com"]
for x in a[:]:
    if len(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):
    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为可选的,实际不用输入)
  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+vec2 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 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  
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
uAunicode和str类似,不过返回Unicode字符串.  
6.4.2. 比较操作
  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:
    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
    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]

  目录

  • Py常用模块汇编

    • zshelve 对象持久模块

      • 发布
      • 补丁::

    • fast UserDict



  CPUG联盟::
  CPUG::门户plone
  BPUG
  SPUG
  ZPUG
  SpreadPython Python宣传
  
7. Py常用模块汇编
  'Python 标准库2.0 整理者
Python 江湖 QQ 群: 43680167
Feather (校对) gt: andelf@gmail.com  一些有用的Python函式庫列表 &#187; 程式設計 遇上 小提琴

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


  CPUG联盟::
  CPUG::门户plone
  BPUG
  SPUG
  ZPUG
  SpreadPython Python宣传
  
7.1. zshelve 对象持久模块
  {{{Jiahua Huang  reply-to        python-cn@googlegroups.com, to      "python. cn" , 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)
  

  •   一行代码让 UserDict.UserDict 的类加速 4 倍
   ::-- ZoomQuiet [2007-11-10 07:34:49]

  目录

  • fast UserDict
  
7.2. fast UserDict
  {{{Jiahua Huang  reply-to        python-cn@googlegroups.com, to      "python. cn" , 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")
0.1777961254119873
>>> _timeit("for i in ran: r=i")
0.048948049545288086
看看原始 dict 的速度
>>> _timeit("for i in ran: d=i")
0.041368961334228516  可以看到, UserDict.UserDict 确实严重影响速度,
  python 标准库里边好多 UserDict 的都应该换成 dict , 以提高性能
  不过,一个个修改 Python 标准库似乎又不合适,
  再次使用一招鲜,直接干掉 UserDict
  在使用/导入那些模块前先来一行
>>> import UserDict; UserDict.UserDict = dict  完了再导入模块来试试
>>> u = URdict()
>>> _timeit("for i in ran: u=i")
0.042366981506347656  一行代码让速度提高 4 倍

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-59480-1-1.html 上篇帖子: 初试PyOpenGL四 (Python+OpenGL)GPU粒子系统与基本碰撞 下篇帖子: Python基础教程,一本可以帮助你快乐学习Python的好书
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表