装饰器补充(叠加多个装饰器)
上节课我们遗留下一个问题,那就是,装饰器到底可不可以叠加?可以叠加的话那么它的执行顺序又是什么?
装饰器的叠加是在函数上方以@形式的语法糖将装饰器加到上面,可以加多个装饰器。装饰器的加载顺序是自下而上,但是执行顺序则是自上而下
from functools import wraps
import time
def timmer(func):
'''
为函数加入计算时间的功能
:param func: 用于接收用户传入的参数
:return:
'''
@wraps(func) # 将函数名与装饰器的调用结果合二为一,使装饰器变得完美
def wrapper1(*args,**kwargs):
print('hello world')
start = time.time()
res = func(*args,**kwargs)
stop = time.time()
print('run time is %s'%(stop - start))
return res
return wrapper1
def auth(engine = 'file'):
'''
为用户加入认证功能
:param engine: 用于接收用户传入的文件类型
:return:
'''
def inner(func):
def wrapper2(*args,**kwargs):
print('hello world'.lower())
name = input('input your name>>: ').strip()
pwd = input('input your password>>: ').strip()
if engine == 'file':
print('文件认证')
if name == 'klf' and pwd == '123':
print('login successful')
res = func(*args,**kwargs)
return res
elif engine == 'mysql':
print('mysql认证')
elif engine == 'ladp':
print('ladmp认证')
else:
print('错误的认证')
return wrapper2
return inner
@auth(engine='mysql') # 将不改变wrapper1功能的前提下再加入认证功能,将index = auth(index) 等同于调用auth内的wrapper2
@timmer # 将timmer(index) = index , 等同于调用wrapper1
def index():
print('welecome to Shanghai')
time.sleep(2)
迭代器
1.什么是迭代器?
迭代也是重复的意思,迭代器就是重复做某件事情的工具,而每次做的事情都是根据上一次事情的结果而来的
2.为什么要用迭代器?
迭代器的主要用途是运用于取值,相比while起来迭代器要更为简便,因为它可以不依赖于索引去取值。
3.如何使用迭代器?
在使用迭代器之前我们需要了解两个知识点:
什么是可迭代对象?:
往大的去说就是在python解释器内,但凡内置(即名字后缀可以使用)有__iter__方法的对象都属于可迭代对象。例如:字符串,列表,字典,元组,集合,文件都属于可迭代对象
什么是迭代器对象?:
在python解释器内,内置不仅有__iter__,还有__next__的对象就属于迭代器对象,而在python解释器中自带迭代器对象的就只有文件!
那么我们如果想要使用迭代器对象的话就需要在名字后边加上__iter__然后赋值给一个变量名,这个变量名就已经是一个迭代器对象了!而调用本身就已经是迭代器对象的名称,则会调到迭代器本身!
dic={'x':1,'y':2,'z':3} iter_dic=dic.__iter__() 调用iter生成迭代器对象 print(iter_dic) res1=iter_dic.__next__() 迭代器对象可以后缀__next__ print(res1)
res2=iter_dic.__next__() 加入next则会取出基于上次结果的下一个值
print(res2) 列表只有三个值,若取res4则会报错。
print(dic.__iter__().__next__()) 在重复的造迭代器对象,每一个都是一个新的迭代器对象,所以每次取值都是从头开始
print(dic.__iter__().__next__())
print(dic.__iter__().__next__())
for循环与while循环回顾
之前我们了解的for循环仅仅是知道for循环取值要比while方便,现在了解了迭代器可以说是for循环就是for迭代器循环,而while循环则主要运用与重复和不停的做某件事,比起for循环功能要更加的强大,但在取值这一层面还是要比for循环更逊色一点。
for循环工作原理:
dic={'x':1,'y':2,'z':3} for k in dic: #此时的dic已经成为了一个迭代器对象然后赋值给 iter_dic = dic.__iter__() #然后执行迭代器iter_dic的next功能得到一个返回值,然后赋值给变量名k,接着运行循环体代码 print(k) #知道迭代器取值完毕后不能再取时抛出异常然后自动捕捉异常结束循环 (捕捉异常 try , except StopIteration)
自定义迭代器
什么是自定义迭代器?
在函数内,但凡包有yield关键字,再去执行函数,就不会再立刻运行函数体代码则会得到一个返回值,该返回值称之为生成器对象,而生成器本质就是迭代器。
yield的作用:
1.提供一种自定义迭代器的解决方案
2.yield可用于返回值,不同于return的是,函数体在遇到yield时,不会停止运行函数体而是暂停,而在函数体内加入多个yield时,则会返回多个值。
def my_range(start,stop,step=1): while start < stop: yield start 自定义迭代器模板 start+=step
三元表达式
可将简单的判断类型的语句使用一行代码实现
def max(x,y) if x > y return x else: return y ----------------------------------------- 使用三元表达式的效果 res = x if x > y else:y 条件成立 判断 条件不成立
列表推导式
可将要添加到列表内的代码简单化,使用一行即可实现
l = [] for i in range(1,10) if i > 4: res = '%segg'%(i) l.append(res) print(res) ------------------------------- 使用一行代码实现 l = ['%segg'%(i) for i in range(1,10) if i > 4] 此时在列表内直接for循环添加就不需要append print(l)
生成器表达式
使用生成器表达式也可以将简单的生成器一行代码轻松实现
res=(i**2 for i in range(3)) print(res) print(next(res)) print(next(res)) 注:条件只到3,不要忘了range的特性顾头不顾尾,所以只有0,1,2三个值。再取值则会报错 print(next(res))
with open(r'user_info',mode='r',encoding='utf-8') as f:
res = f.read() #一次性将文件所有内容读入内存并计算
print(len(res)) #若文件较大则会使系统崩溃
res = 0
for line in f: #使用for循环则会一层层的将文件读入内存,不会对内存造成影响
res+=len(line)
print(res)
res = sum((len(line) for line in f)) #使用sum求和功能将for循环使用一行代码实现!
res = sum(len(line) for line in f) #使用sum求和功能若外层有多余的小括号可去掉使代码更简洁
字典生成式
同上,将要添加到新字典的代码也可使用for循环一行实现~
items = [('name','klf'),('age',18),('sex','male')] dic = {} #定义空字典 for k,v in items: dic[k] = v #dic[k] = v 等同于 k:v print(dic) dic = {k:v for k,v in items} #涨姿势了~ print(dic)