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