python基础语法8 叠加装饰器,有参装饰器,wraps补充,迭代器
叠加装饰器:
叠加装饰器
- 每一个新的功能都应该写一个新的装饰器
- 否则会导致,代码冗余,结构不清晰,可扩展性差
在同一个被装饰对象中,添加多个装饰器,并执行。
@装饰1
@装饰2
@装饰3
def 被装饰对象():
pass
注意: 装饰器在调用被装饰对象时才会执行添加的功能。
- 叠加装饰器:
- 装饰的顺序: 由下到上装饰
- 执行的顺序: 由上往下
注意: 无论inner中出现任何判断,最后都要返回“调用后的被装饰对象” func(*args, **kwargs)
def wrapper1(func): def inner1(*args, **kwargs): print('1---start') # 被裝飾對象在調用時,如果還有其他裝飾器,會先執行其他裝飾器中的inner # inner2 res = func(*args, **kwargs) print('1---end') return res return inner1 def wrapper2(func): def inner2(*args, **kwargs): print('2---start') res = func(*args, **kwargs) print('2---end') return res return inner2 def wrapper3(func): def inner3(*args, **kwargs): print('3---start') res = func(*args, **kwargs) print('3---end') return res return inner3 ''' 叠加裝飾器的裝飾順序與執行順序: - 裝飾順序: 调用wrapper装饰器拿到返回值inner 由下往上裝飾 - 執行順序: 调用装饰过后的返回值inner 由上往下執行 ''' @wrapper1 # index《---inner1 = wrapper1(inner2) @wrapper2 # inner2 = wrapper2(inner3) @wrapper3 # inner3 = wrapper3(index) def index(): # 被裝飾對象 # inner1 ---》 print('from index...') # 正在装饰 index = wrapper3(index) index = wrapper2(index) index = wrapper1(index) ''' inner1() inner2() inner3() index() ''' index() # 此处执行 # inner1() --> inner2() ---> inner3()
有参装饰器
# 无参装饰器: 装饰在被装饰对象时,没有传参数的装饰器。 ''' # 以下是无参装饰器 @wrapper1 # inner1 = wrapper1(inner2) @wrapper2 # inner2 = wrapper2(inner3) @wrapper3 ''' # 有参装饰器: 在某些时候,我们需要给用户的权限进行分类 ''' # 以下是有参装饰器 @wrapper1(参数1) # inner1 = wrapper1(inner2) @wrapper2(参数2) # inner2 = wrapper2(inner3) @wrapper3(参数3) '''
def user_auth(user_role): # 'SVIP' def wrapper(func): def inner(*args, **kwargs): if user_role == 'SVIP': # 添加超级用户的功能 res = func(*args, **kwargs) return res elif user_role == '普通用户': print('普通用户') # 添加普通用户的功能 res = func(*args, **kwargs) return res return inner return wrapper # 被装饰对象 user_auth('SVIP') 等价于下面两行代码 wrapper = user_auth('普通用户') @wrapper # @user_auth('SVIP') # wrapper = user_auth('普通用户') #@wrapper #<--- 返回结果(wrapper) <---- user_auth() def index(): pass # wrapper = user_auth('普通用户') 等价于这两行 # index=wrapper(index) index()
wraps: (了解)
是一个修复工具,修复的是被装饰对象的空间。不用显示外层装饰器注释
from functools import wraps
from functools import wraps def wrapper(func): @wraps(func) # 修改名称空间: inner ---》 func 不写此处变为装饰器注释 def inner(*args, **kwargs): ''' 此处是装饰器的注释 :param func: :return: ''' res = func(*args, **kwargs) return res return inner # ---》 func @wrapper def index(): ''' 此处是index函数的注释 :return: ''' pass print(index) # 函数对象 # 函数对象.__doc__: 查看函数内部的注释 print(index.__doc__) # inner.__doc__
迭代器
- 迭代器
迭代的工具。
迭代:
迭代指的是重复迭代,每一次迭代都是基于上一次的结果而来的。
迭代器:
迭代器指的是迭代取值的工具,它可以迭代取值。
- 如果想要知道python中迭代器是什么?必须先知道什么是可迭代对象?
可迭代对象: 所有的序列类型: str, list, tuple, dict, set, f
凡是内部有str.__iter__()方法的都是可迭代对象。
- 获取迭代器:
通过可迭代对象.__iter__(), 得到的返回值就是 “迭代器对象”。
迭代器是迭代取值的工具,作用是迭代取值。
- 如何迭代取值:
迭代器对象.__next__() # “每一次执行”,都会从迭代器对象中取出一个值
- 总结: 可迭代对象 VS 迭代器对象:
- 获取可迭代对象: 定义序列类型(str, list, set, tuple, dict, f)
- 特点:
内置有__iter__()
- 获取迭代器对象: 通过可迭代对象调用.__iter__()得到返回值
- 特点:
内置有__next__()
- 迭代器对象的优点:
- 优点:
1.不依赖于索引迭代取值。
2.节省内存空间。
- 缺点:
1.取指定某个值麻烦
2.每次取值都要从第一个值开始,无法同过索引取值。
3.不能通过len计算长度
# 以下都是可迭代对象 ''' str1 = 'hello tank!' str1.__iter__() list1 = [1, 2, 3] # list([1, 2, 3]) list1.__iter__() set.__iter__() dict.__iter__() tuple.__iter__() open('a.txt').__iter__() '''
# list1是一个可迭代对象 list1 = ['tank', 'jason鸡哥', 'sean', '饼哥'] # 获取迭代器对象: iter_list1 iter_list1 = list1.__iter__() while True: # 补充: try: 捕获异常 try: print(iter_list1.__next__()) # 报错 # 立即触发此处代码 StopIteration except StopIteration: break
测试迭代文件 f = open('user.txt', 'r', encoding='utf-8') iter_f = f.__iter__() while True: try: print(iter_f.__next__()) except StopIteration: break
for循环本质
for循环原理
语法: for i in 可迭代对象:
in: 可迭代对象 ----> 内部会自动调用.__iter__() ---> 迭代器对象
for i in 可迭代对象:
# 会自定帮你调用__next__
print(i)
# for循环内部也会有一个捕获异常机制,一旦遇到异常也会停止取值。
list1 = [1, 2, 3, 4] for line in list1: # list1是可迭代对象 ----> 内部会自动调用.__iter__() ---> 迭代器对象 # 迭代器对象.__next__() print(line)
迭代器对象
- 迭代器本质上是一个可迭代对象
- 文件本质上既是迭代器对象,也是可迭代对象。
- 可迭代对象不一定是迭代器对象
iter_set1 = set1.__iter__() iter_set1.__next__() # 确定: 迭代器对象也是一个可迭代对象 # 判断可迭代对象是否是迭代器对象 # print(iter_set1.__iter__() is iter_set1) # True # 唯独文件比较特殊: 因为文件从读取出来的时候就是一个迭代器对象 # f ---> 可迭代对象, 还是迭代器对象 # f = open('user.txt', 'r', encoding='utf-8') # f.__next__() # # # # 确定: 文件既是可迭代对象,也是迭代器对象。 # # # iter_f ---> 迭代器对象 # iter_f = f.__iter__() # iter_f.__next__() ''' list1 = [1, 2, 3] # 迭代器对象 iter_list = list1.__iter__() str1 = '123' # 迭代器对象 iter_str1 = str1.__iter__() print(iter_list is iter_str1) # False ''' # 可迭代对象 list1 = [1, 2, 3, 4] # iter_list1 ---> 迭代器对象 iter_list1 = list1.__iter__() print(iter_list1 is list1) # False # 可迭代对象不一定是迭代器对象