函数进阶篇

mac2022-06-30  65

1.1 装饰器

1.1.1 开放封闭原则:

对扩展开放,对修改是封闭

1.1.2 装饰器:

装饰它人的,器指的是任意可调用对象,现在的场景装饰器-》函数,被装饰的对象也是-》函数

1.1.3 原则:

1、不修改被装饰对象的源代码

2、不修改被装饰对象的调用方式

1.1.4 装饰器的目的:

在遵循1,2的前提下为被装饰对象添加上新功能

错误的示范

import time def index(): time.sleep(3) print('welecome to index') def timmer(func): start=time.time() func() stop=time.time() print('run time is %s' %(stop-start)) timmer(index)

1.1.5 正确的示范

import time def index(): time.sleep(3) print('welecome to index') def timmer(func): # func=index #最原始的index def inner(): start=time.time() func() #最原始的index stop=time.time() print('run time is %s' %(stop-start)) return inner index=timmer(index) #index=inner # print(f) index() #inner()

 

1.2 装饰器的修订

1.2.1 装饰器语法:

在被装饰对象正上方单独一行写上,@装饰器名

@deco1 @deco2 @deco3 def foo(): pass foo=deco1(deco2(deco3(foo)))

 

1.2.2 改进一:

import time def timmer(func): def inner(): start=time.time() res=func() stop=time.time() print('run time is %s' %(stop-start)) return res return inner @timmer #index=timmer(index) def index(): time.sleep(1) print('welecome to index') return 1111 res=index() #res=inner() print(res)

1.2.3 改进二:

import time def timmer(func): def inner(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop-start)) return res return inner @timmer #index=timmer(index) def index(name): time.sleep(1) print('welecome %s to index' %name) return 1111 res=index('egon') #res=inner('egon') print(res) @timmer #home=timmer(home) def home(name): print('welcome %s to home page' %name) home('egon') #inner('egon')

 

1.3 有参装饰器

import time def auth(func): # func=index def inner(*args,**kwargs): name=input('name>>: ').strip() password=input('password>>: ').strip() if name == 'egon' and password == '123': print('login successful') return func(*args,**kwargs) else: print('login err') return inner @auth def index(name): time.sleep(1) print('welecome %s to index' %name) return 1111 res=index('egon') print(res)

#有参装饰器

import time def auth2(engine='file'): def auth(func): # func=index def inner(*args,**kwargs): if engine == 'file': name=input('name>>: ').strip() password=input('password>>: ').strip() if name == 'egon' and password == '123': print('login successful') return func(*args,**kwargs) else: print('login err') elif engine == 'mysql': print('mysql auth') elif engine == 'ldap': print('ldap auth') else: print('engin not exists') return inner return auth @auth2(engine='mysql') #@auth #index=auth(index) #index=inner def index(name): time.sleep(1) print('welecome %s to index' %name) return 1111 res=index('egon') #res=inner('egon') print(res) View Code

1.4 并列多个装饰器

import time def timmer(func): def inner(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop-start)) return res return inner def auth2(engine='file'): def auth(func): # func=index def inner(*args,**kwargs): if engine == 'file': name=input('name>>: ').strip() password=input('password>>: ').strip() if name == 'egon' and password == '123': print('login successful') return func(*args,**kwargs) else: print('login err') elif engine == 'mysql': print('mysql auth') elif engine == 'ldap': print('ldap auth') else: print('engin not exists') return inner return auth @auth2(engine='file') @timmer def index(name): time.sleep(1) print('welecome %s to index' %name) return 1111 res=index('egon') print(res)

1.5 wraps补充

from functools import wraps import time def timmer(func): @wraps(func) def inner(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop-start)) return res # inner.__doc__=func.__doc__ # inner.__name__=func.__name__ return inner @timmer def index(name): #index=inner '''index 函数。。。。。''' time.sleep(1) print('welecome %s to index' %name) return 1111 # res=index('egon') # print(res) print(help(index))

1.6 迭代器:

迭代的工具

1.6.1 什么是迭代:

指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果是下一次重复的初始值 while True: print('=====>')

 

l=['a','b','c'] count=0 while count < len(l): print(l[count]) count+=1

  

1.6.2 为什么要有迭代器?

对于序列类型:str,list,tuple,可以依赖索引来迭代取值, 但是对于dict,set,文件,python必须为我们提供一种不依赖于索引的迭代取值的方式-》迭代器  

1.6.3 可迭代的对象(下列都是):obj.__iter__

name='egon' l=[1,2,3] t=(1,2,3) d={'name':'egon','age':18,'sex':'male'} s={'a','b','c'} f=open('a.txt','w',encoding='utf-8')

 

name.__iter__ l.__iter__ t.__iter__ d.__iter__ s.__iter__ f.__iter__  

1.6.4 迭代器对象(文件是):obj.__iter__,obj.__next__

f.__iter__ f.__next__

1.6.5 总结:

1 可迭代对象不一定是迭代器对象 2 迭代器对象一定是可迭代的对象 3 调用obj.__iter__()方法,得到的是迭代器对象(对于迭代器对象,执行__iter__得到的仍然是它本身)    d={'name':'egon','age':18,'sex':'male'} d_iter=d.__iter__()

 

f=open('a.txt','w',encoding='utf-8') f_iter=f.__iter__().__iter__().__iter__().__iter__() print(f_iter is f) d={'name':'egon','age':18,'sex':'male'} d_iter=d.__iter__() print(d_iter.__next__()) print(d_iter.__next__()) print(d_iter.__next__()) print(d_iter.__next__())

迭代器d_iter没有值了,就会抛出异常StopIteration

f=open('a.txt','r',encoding='utf-8') print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__()) f.close() l=['a','b','c'] l_iter=l.__iter__() print(l_iter.__next__()) print(l_iter.__next__()) print(l_iter.__next__()) print(l_iter.__next__()) d={'name':'egon','age':18,'sex':'male'} d_iter=iter(d) #d_iter=d.__iter__()  len(obj) 等同于obj.__len__()

1.6.6 for循环的本质

while True: try: print(next(d_iter)) #print(d_iter.__next__()) except StopIteration: break print('=>>>') print('=>>>') print('=>>>') print('=>>>')

 

for循环详解:

1、调用in后的obj_iter=obj.__iter__() 2、k=obj_iter.__next__() 3、捕捉StopIteration异常,结束迭代 d={'name':'egon','age':18,'sex':'male'} for k in d: print(k)

1.6.7 总结迭代器的优缺点:

1.6.71  优点:

1、提供一种统一的、不依赖于索引的取值方式,为for循环的实现提供了依据 2、迭代器同一时间在内存中只有一个值——》更节省内存,  

1.6.72  缺点:

1、只能往后取,并且是一次性的 2、不能统计值的个数,即长度 l=[1,2,3,4,5,6] l[0] l[1] l[2] l[0] l_iter=l.__iter__() # print(l_iter) print(next(l_iter)) print(next(l_iter)) print(next(l_iter)) print(next(l_iter)) print(next(l_iter)) print(next(l_iter)) print(next(l_iter))   l_iter=l.__iter__() print(next(l_iter)) print(next(l_iter)) print(next(l_iter)) print(len(l_iter))

1.7 生成器

1.7.1 什么是生成器:

只要在函数体内出现yield关键字,那么再执行函数就不会执行函数代码,会得到一个结果,该结果就是生成器

def func(): print('=====>1') yield 1 print('=====>2') yield 2 print('=====>3') yield 3 生成器就是迭代器 g=func() res1=next(g) print(res1) res2=next(g) print(res2) res3=next(g) # print(res3)

1.7.2 yield的功能:

1、yield为我们提供了一种自定义迭代器对象的方法 2、yield与return的区别1:yield可以返回多次值 #2:函数暂停与再继续的状态是由yield帮我们保存的  obj=range(1,1000000000000000000000000000000000000000000000000000000000000000,2) obj_iter=obj.__iter__() print(next(obj_iter)) print(next(obj_iter)) print(next(obj_iter)) print(next(obj_iter)) print(next(obj_iter))  def my_range(start,stop,step=1): while start < stop: yield start #start=1 start+=step #start=3 g=my_range(1,5,2) print(g) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) for i in my_range(1,5,2): print(i)

  

1.7.3 小练习::tail -f access.log | grep '404'

import time def tail(filepath): with open(filepath,'rb') as f: f.seek(0,2) while True: line=f.readline() if line: yield line else: time.sleep(0.05) def grep(lines,pattern): for line in lines: line=line.decode('utf-8') if pattern in line: yield line lines=grep(tail('access.log'),'404') for line in lines: print(line)

 

1.7.4 yield表达式形式的用法(了解知识点)

def eater(name): print('%s ready to eat' %name) food_list=[] while True: food=yield food_list#food=yield='一盆骨头' food_list.append(food) print('%s start to eat %s' %(name,food)) e=eater('alex') #首先初始化: print(e.send(None)) # next(e) #然后e.send:1 从暂停的位置将值传给yield 2、与next一样 print(e.send('一桶泔水')) print(e.send('一盆骨头'))

1.8 追加文件

with open('access.log','a',encoding='utf-8') as f: f.write('bbbbb 404\n') f.flush()

 

1.9 面向过程编程

grep -rl 'python' /etc 补充:os.walk import os g=os.walk(r'D:\video\python20期\day4\a') # print(next(g)) # print(next(g)) # print(next(g)) # print(next(g)) for pardir,_,files in g: for file in files: abs_path=r'%s\\%s' %(pardir,file) print(abs_path)  

1.9.1 分析一:

1.9.11  第一步:拿到一个文件夹下所有的文件的绝对路径

import os def search(target): #r'D:\video\python20期\day4\a' while True: filepath=yield #fllepath=yield=r'D:\video\python20期\day4\a' g=os.walk(filepath) for pardir, _, files in g: for file in files: abs_path = r'%s\%s' % (pardir, file) # print(abs_path) target.send(abs_path) search(r'D:\video\python20期\day4\a') search(r'D:\video\python20期\day4')

 

1.9.12  第二步:打开文件拿到文件对象f

def opener(): while True: abs_path=yield print('opener func--->',abs_path) target=opener() next(target) #target.send('xxxx') g=search(target) next(g) g.send(r'D:\video\python20期\day4\a')

 

1.9.2 分析二:

1.9.21  第一步:拿到一个文件夹下所有的文件的绝对路径

import os def init(func): def inner(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return inner @init def search(target): # r'D:\video\python20期\day4\a' while True: filepath = yield g = os.walk(filepath) for pardir, _, files in g: for file in files: abs_path = r'%s\%s' % (pardir, file) #把abs_path传给下一个阶段 target.send(abs_path)

1.9.22  第二步:打开文件拿到文件对象f

@init def opener(target): while True: abs_path = yield with open(abs_path,'rb') as f: #把(abs_path,f)传给下一个阶段 target.send((abs_path,f))

1.9.23  第三步:读取f的每一行内容

@init def cat(target): while True: abs_path,f=yield for line in f: #把(abs_path,line)传给下一个阶段 res=target.send((abs_path,line)) #满足某种条件,break掉for循环 if res: break

1.9.24  第四步:判断'python' in line

@init def grep(target,pattern): pattern = pattern.encode('utf-8') res=False while True: abs_path,line=yield res res=False if pattern in line: #把abs_path传给下一个阶段 res=True target.send(abs_path)

1.9.25  第五步:打印文件路径

@init def printer(): while True: abs_path=yield print('<%s>'
转载请注明原文地址: https://mac.8miu.com/read-18129.html
最新回复(0)