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)
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 ') f.flush()
1.9 面向过程编程
grep -rl 'python' /etc
补充:os.walk
import os g=os.walk(r'D:videopython20期day4a') # 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:videopython20期day4a' while True: filepath=yield #fllepath=yield=r'D:videopython20期day4a' 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:videopython20期day4a') search(r'D:videopython20期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:videopython20期day4a')
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:videopython20期day4a' 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>' %abs_path) g=search(opener(cat(grep(printer(),'python')))) #'python' in b'xxxxx' g.send(r'D:videopython20期day4a')
面向过程编程:核心是过程二字,过程指的就是解决问题的步骤,即先干什么后干什么,基于该思路编写程序就好比设计一条流水线,是一种机械式的思维方式
1.9.3 面向过程编程优缺点
优点:
复杂的问题流程化、进而简单化
缺点:
可扩展性差
1.10 三元表达式
def my_max(x,y): if x >= y: return x else: return y x=10 y=20 # res=x if x >= y else y # print(res) name=input('>>: ').strip() res='Sb' if name == 'alex' else 'NB' print(res)
1.11 列表推导式与生成器表达式
1.11.1 列表推导式
l=[] for i in range(1,11): res='egg'+str(i) l.append(res) print(l) l=['egg'+str(i) for i in range(1,11)] print(l) l1=['egg'+str(i) for i in range(1,11) if i >= 6] print(l1) l1=[] for i in range(1,11): if i >= 6: l1.append('egg'+str(i))
1.11.2 生成器表达式
g=('egg'+str(i) for i in range(0,1000000000000000000000000000000000)) print(g) print(next(g)) print(next(g)) print(next(g))
1.11.3 练习
names=['egon','alex_sb','wupeiqi','yuanhao'] names=[name.upper() for name in names] print(names) sbs=[name for name in names if name.endswith('sb')] print(sbs) obj=list('abcdef') print(obj) print(max([1,2,3,4,5])) g=(i for i in range(10)) print(max(g)) print(max(g)) with open('a.txt','r',encoding='utf-8') as f: l=[] for line in f: # print(len(line)) l.append(len(line)) g=(len(line) for line in f) res=max(g) print(res) print(max(len(line) for line in f)) print(sum(len(line) for line in f))
1.12 递归调用:
在调用一个函数的过程中,直接或者间接又调用该函数本身,称之为递归调用
1.12.1 递归必备的两个阶段:
1、递推
2、回溯
import sys print(sys.getrecursionlimit()) sys.setrecursionlimit(2000) print(sys.getrecursionlimit()) def func(n): print('---->',n) func(n+1) func(0) def bar(): print('from bar') func() def func(): print('from func') bar() func() age(5) = age(4) + 2 age(4) = age(3) + 2 age(3) = age(2) + 2 age(2) = age(1) + 2 age(1) = 18 age(n)=age(n-1)+2 # n > 1 age(1) = 18 #n = 1 def age(n): if n == 1: return 18 return age(n-1) + 2 res=age(5) print(res) l=[1,[2,[3,[4,[5,[6,[7,]]]]]]] def func(l): for item in l: if type(item) is list: func(item) else: print(item) def func(): print('===>') func() func()
1.13 二分法(了解的知识点)
l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表 def binary_search(l,num): print(l) if len(l) == 0: print('not exists') return mid_index=len(l) // 2 if num > l[mid_index]: #往右找 binary_search(l[mid_index+1:],num) elif num < l[mid_index]: #往左找 binary_search(l[0:mid_index],num) else: print('find it') # binary_search(l,301) binary_search(l,302)
1.14 匿名函数
def func(): #func=内存地址 print('from func') func() func()
def my_sum(x,y): return x+y
print(lambda x,y:x+y) print((lambda x,y:x+y)(1,2))
func=lambda x,y:x+y # print(func) print(func(1,2))
max,min,sorted,map,reduce,filter
salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 } print(max(salaries))
s='hello' l=[1,2,3] g=zip(s,l) # print(g) print(list(g))
g=zip(salaries.values(),salaries.keys()) # print(list(g)) print(max(g)) def func(k): return salaries[k] print(max(salaries,key=func)) #key=func('egon') print(max(salaries,key=lambda k:salaries[k])) #key=func('egon') print(min(salaries,key=lambda k:salaries[k])) #key=func('egon')
sorted
salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 } print(sorted(salaries,key=lambda k:salaries[k])) print(sorted(salaries,key=lambda k:salaries[k],reverse=True))
map,reduce,filter
names=['alex','wupeiqi','yuanhao'] l=[] for name in names: res='%s_SB' %name l.append(res) print(l) g=map(lambda name:'%s_SB' %name,names) # print(g) print(list(g))
names=['alex_sb','wupeiqi_sb','yuanhao_sb','egon'] g=filter(lambda x:x.endswith('sb'),names) print(g) print(list(g))
from functools import reduce print(reduce(lambda x,y:x+y,range(1,101),100))
1.15 内置函数(了解)
print(abs(-1))
print(all([1,'a','b',0])) print(all([]))
print(any([None,False,0,1])) print(any([]))
print(bin(11)) print(hex(11)) print(oct(11))
print('xxx'.encode('utf-8')) print(bytes('xxx',encoding='utf-8'))
print(callable(max))
print(chr(65)) # print(chr(90)) # print(chr(39)) print(ord('A')) print(ord('@'))
import os
print(dir(os)) s=set({1,2,3}) s.add(4) print(s)
s=frozenset({1,2,3}) #不可变集合 print(hash('xxx'))
l=[1,2,'a',4] print(list(reversed(l)))
s=slice(1,5,2) l=['a','b','c','d','e']
# print(l[1:5:2]) # print(l[1:5:2]) print(l[s])
print(vars() is locals())
obj.__dict__() #vars(obj)
1.16 面向对象
classmethod
staticmethod
property
hasattr
getattr
setattr
delattr
isinstance
issubclass
object
super
import
__import__ choice=input('>>: ') print(choice,type(choice)) # import 'time' m=__import__(choice) m.sleep(10)
1.17 掌握:
1.17.1 divmod
# print(divmod(10011,25))
1.17.2 enumerate
l=['a','b','c'] for i in l: print(l.index(i),i,) for i,v in enumerate(l): print(i,v)
1.17.3 eval:
res=eval('[1,2,3]') print(res,type(res)) res=exec('[1,2,3]') print(res)
1.17.4 pow
res=pow(2,3,3) # (2 ** 3 )%3 print(res)
1.17.5 round
print(round(3.5))