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 '\033[31;1m%s\033[0m:\n\033[32;1m%s\033[0m\n' % (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:\n%s\n' % (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 '\033[31;1m%s\033[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()
[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()
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步