zoukankan      html  css  js  c++  java
  • python 基础之第十天(闭包,装饰器,生成器,tarfile与hashlib模块使用)

    局部变量与全局变量

    局部变量:在函数里面定义的,只有当函数活动时才生效

    全局变量:不在函数里面的

    In [1]: x=10
    
    In [2]: def bar():
       ...:     x=20
       ...:     print x
       ...:     
    
    In [3]: x
    Out[3]: 10
    
    #####如果一定要改变全局的变量,使用global参数####
    In [5]: def bar():
       ...:     global x
       ...:     x = 20
    
    In [6]: x
    Out[6]: 10
    
    In [7]: bar()
    
    In [8]: x
    Out[8]: 20

    ########################################################################

    有个需求:x,y 的和,x一直都是10,每次调用都要输入10,很麻烦,用add10 = partial(add,10)  就只需要输入一次

    from functools import partial
    
    def add(x,y):
        return x+y
    
    if __name__ == '__main__':
         print add(10,20)
         print add(10,40)
         print add(10,89)
         add10 = partial(add,10)
         print add10(50)

    结果:

    [root@master script]# python add10.py
    30
    50
    99
    60

    ################列出所有目录下的文件#############

    [root@master script]# vim lsdir.py          
    #!/usr/bin/python
    # coding:utf-8
    
    
    import sys
    import os
    
    
    
    def lsdir(folder):
        contents = os.listdir(folder)
        print '33[31;1m%s33[0m:
    33[32;1m%s33[0m
    ' % (folder,contents)
        for item in contents:
            full_path = os.path.join(folder,item)
            if os.path.isdir(full_path):
                lsdir(full_path)
    
    
    if __name__ == '__main__':
        lsdir(sys.argv[1])

    效果:

    [root@master script]# python lsdir.py /home/
    /home/:
    ['herry', 'honey', '11111.txt', 'hosts', 'fush', 'jerry', 'mima', 'demo', 'cesh.txt', 'fush.txt', 'master']
    
    /home/herry:
    ['.bashrc', '.bash_logout', '.bash_profile']
    
    /home/honey:
    ['.bashrc', '.bash_logout', '.bash_profile']
    
    /home/fush:
    ['.bashrc', '.bash_logout', '.bash_profile']
    
    /home/jerry:
    ['.bashrc', '.bash_logout', '.bash_profile']

    ############lsdir2.py#################

    [root@master script]# vim lsdir2.py          
    #!/usr/bin/python
    
    
    import os
    import sys
    
    
    def lsdir(folder):
        for path,dirs,files in os.walk(folder):
            print '%s:
    %s
    ' % (path,(dirs+files))
    
    
    
    if __name__ == '__main__':
        lsdir(sys.argv[1])

     ######################闭包(重点也是难点)###############

    代码:

    [root@master script]# vim counter.py   
    #!/usr/bin/python
    
    def conter(start_at=0):
        count = [start_at]
        def incr():
            count[0] += 1
            return count[0]
        return incr
    
    if __name__ == '__main__':
        a = conter()
        print a();print a()
        b = conter(10)
        print b();print b()
        print a()
        print b()

    效果:

    [root@master script]# python counter.py
    1
    2
    11
    12
    3
    13

     ##################装饰器###############

    #time模块的简单用法

    In [1]: import time
    
    In [2]: time.time()
    Out[2]: 1503037729.0894251    #距离1970 年的秒数,也就是当前时间的时间戳
    
    In [3]: time.ctime(1503037729.0894251)   #换算成当前时间
    Out[3]: 'Fri Aug 18 14:28:49 2017'

    计算程序花了多长时间代码例子:

    [root@master script]# vim loo.py   
    #!/usr/bin/python
    # coding:utf-8
    
    import time
    
    
    def loop():
        result = []
        for i in range(1,6):
            result.append(i)
            time.sleep(1)
        return result
    
    if __name__ == '__main__':
        start = time.time()
        print loop()
        end = time.time()
        print 'program is spend_time %.2f' % (end - start)        ###'%.2f'  保留小数点后面两位;'%.3f'  保留小数点后面三位;
    结果: [root@master script]# python loo.py [1, 2, 3, 4, 5] program is spend_time 5.01

    ##################装饰器(python最难点)######################

    [root@master script]# vim loo.py   
    #!/usr/bin/python
    # coding:utf-8
    
    import time
    
    def deco(func):                   ======>func其实等于loop
        def timeit():
            start = time.time()
            res = func()
            end = time.time()
            print 'program is spend_time %.2f' % (end - start)
            return res
        return timeit
    
    
    @deco
    def loop():
        result = []
        for i in range(1,6):
            result.append(i)
            time.sleep(1)
        return result
    
    if __name__ == '__main__':
        print loop()  ===========>   这里并不是直接调用loop函数,因为有装饰器deco,所以loop被当成是装饰器deco的参数,

    另外一个例子:

    [root@master script]# vim font.py   
    #!/usr/bin/python
    # coding:utf-8
    
    
    
    def color(func):
        def color_font(astr):
            return '33[31;1m%s33[0m' % (func(astr))
        return color_font
    
    @color
    def say_hi(word):
        return 'hello %s' % word
    
    @color
    def greet(name):
        return 'welcome %s' % name
    
    
    if __name__ == '__main__':
        print say_hi('tedu')
        print greet('bob')

    结果:

    [root@master script]# python font.py
    hello tedu
    welcome bob

    ################生成器#################

    生成器(就是函数)延时计算,使内存使用的更加有效率。

    有个yield语句,就是类似return,只不过return在函数里面只能返回一个值(就算有多个return)也只返回一个,而yield 则可以每执行一次返回一个中间结果,并且不是从头开始,而是从上次的地方开始,继续执行。

    生成器都有一个next()方法。

    例子:(把文件的每10行返回一次)

    [root@master script]# vim yeid.py
    #!/usr/bin/python
    # coding:utf-8
    
    
    def block(fobj):
        block = []
        counter = 0
        for line in fobj:
            block.append(line)
            counter += 1
            if counter == 10:
                yield block
                counter = 0
                block = []
        yield block
    
    
    
    
    
    if __name__ == '__main__':
        with open('/etc/passwd') as fobj:
            for line in block(fobj):
                print line

    ############从zip文件中导入##############

    #######例子:

    [root@master script]# zip ran.zip ranpass.py
    [root@master script]# pwd
    /home/master/script
    [root@master script]# ll
    -rw-r--r-- 1 root root  352 Aug 21 10:34 ran.zip
    -rw-r--r-- 1 root root  300 Aug  4 18:24 ranpass.py
    
    
    In [8]: sys.path
    In [10]: sys.path.append('/home/master/script/ran.zip')
    
    In [12]: sys.path
    Out[12]: 
    ['',
     '/usr/bin',
     '/usr/lib/python2.6/site-packages/thrift-0.10.0-py2.6-linux-x86_64.egg',
     '/usr/lib64/python26.zip',
     '/usr/lib64/python2.6',
     '/usr/lib64/python2.6/plat-linux2',
     '/usr/lib64/python2.6/lib-tk',
     '/usr/lib64/python2.6/lib-old',
     '/usr/lib64/python2.6/lib-dynload',
     '/usr/lib64/python2.6/site-packages',
     '/usr/lib/python2.6/site-packages',
     '/usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg-info',
     '/usr/lib/python2.6/site-packages/IPython/extensions',
     '/home/master/script/ran.zip']
    
    In [13]: import ranpass

    #######################两个常用模块(tarfiel和hashlib)########################

    #######################实践案例########################

     对目录下的文件进行全量备份与增量备份;

    思路及关键点:

    建立一个文件,以字典方式记录src的文件名以及文件对应的md5的值 完全备份的时候将文件名和md5值写在一个文件里面。cPickle的知识点。

    增量备份的时候比较文件名是否在key里面,没有就要备份;有的话,这个文件的md5值是否改变,改变了就要备份 os.path.join()拼接路径,os.listdir(),os.chdir() time.strftime()判断周几 cPickle,可以无损记录所有Python的变量类型。文件操作。 tarfile对文件打包的使用 hashlib用于计算文件md5的值。注意不要一次打开一个文件,4k地打开,防止打开一个超大文件爆内存。 with file()可以打开一个文件之后不f.close()

    常用的函数:
    md5=hashlib.md5()  生成一个md5 hash对象
    md5.update("xxxxxxxxx") 对字符串进行md5更新处理,m.update(a)之后在 m.update(b),相当于m.update(a+b)
    md5.digest() 返回二进制的加密结果
    md5.hexdigest() 返回十六进制的机密结果
    [root@master script]# cat backup_good.py 
    #!/usr/bin/env python
     
    import time
    import os
    import cPickle as p
    import tarfile
    import hashlib
     
    baseDir = '/home/master/script'
    srcDir = 'demo'
    dstDir = 'dst'
    fullName = "full_%s_%s.tar.gz" % (srcDir, time.strftime('%Y%m%d'))
    incrName = "incr_%s_%s.tar.gz" % (srcDir, time.strftime('%Y%m%d'))
    md5file = 'md5.data'
     
    def md5sum(fname):
        m = hashlib.md5()
     
        with file(fname) as f:
            while True:
                data = f.read(4096)
                if len(data) == 0:
                    break
                m.update(data)
     
        return m.hexdigest()
     
    def fullBackup():
        md5Dict = {}
        fileList = os.listdir(os.path.join(baseDir,srcDir))
     
        for eachFile in fileList:
            md5Dict[eachFile] = md5sum(os.path.join(baseDir,srcDir,eachFile))
     
        with file(os.path.join(baseDir,dstDir,md5file),'w') as f:
            p.dump(md5Dict,f)
     
        tar = tarfile.open(os.path.join(baseDir,dstDir,fullName),'w:gz')
        os.chdir(baseDir)
        tar.add(srcDir)
        tar.close()
     
    def incrBackup():
        newmd5 = {}
        fileList = os.listdir(os.path.join(baseDir,srcDir))
        for eachFile in fileList:
            newmd5[eachFile] = md5sum(os.path.join(baseDir,srcDir,eachFile))
        with file(os.path.join(baseDir,dstDir,md5file)) as f:
            storedmd5 = p.load(f)
     
        tar = tarfile.open(os.path.join(baseDir,dstDir,incrName),'w:gz')
        os.chdir(baseDir)
        for eachKey in newmd5:
            if (eachKey not in storedmd5) or (newmd5[eachKey] != storedmd5[eachKey]):
                tar.add(os.path.join(srcDir,eachKey))
        tar.close()
     
        with file(os.path.join(baseDir,dstDir,md5file),'w') as f:
            p.dump(newmd5,f)
     
     
    def main():
        if time.strftime('%a') == 'Mon':
            fullBackup()
        else:
            incrBackup()
     
    if __name__ == '__main__':
        main()
  • 相关阅读:
    SAP CRM WebClient UI上将text area里的文本清空的后台处理
    SAP Business Application Studio的权限控制
    Git安装与配置——详细教程1
    如何在Windows平台下安装配置Memcached
    详解PHP操作Memcache缓存技术提高响应速度的方法
    PHP开发小技巧②—实现二维数组根据key进行排序
    PHP开发小技巧③—实现多维数组转化为一维数组
    PHP开发小技巧①①—php实现手机号码显示部分
    curl实例-通过新浪股票接口获取股票信息
    中国菜刀的功能介绍和使用方法
  • 原文地址:https://www.cnblogs.com/shanhua-fu/p/7374948.html
Copyright © 2011-2022 走看看