叠加装饰器:

  叠加装饰器
    - 每一个新的功能都应该写一个新的装饰器
    - 否则会导致,代码冗余,结构不清晰,可扩展性差

  在同一个被装饰对象中,添加多个装饰器,并执行。
  @装饰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()

有参函数

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.每次取值都要从第一个值开始,无法同过索引取值。

# 以下都是可迭代对象
'''
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 line in list1:
    # 迭代器对象.__next__()

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
# 可迭代对象不一定是迭代器对象
01-02 15:48