Title

函数三大器之迭代器

1.装饰器补充

1.叠加装饰器

  • 装饰的顺序: 由下到上装饰

  • 执行的顺序: 由上往下

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


# 正在装饰
# inner3 = wrapper3(index)
# inner2 = wrapper2(inner3)
# inner1 = wrapper1(inner2)


'''
inner1()
inner2()
inner3()
index()
'''
index()  # 此处执行 # inner1() --> inner2() ---> inner3()

 

2.有参装饰器

# 无参装饰器: 装饰在被装饰对象时,没有传参数的装饰器。
'''
# 以下是无参装饰器
@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
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__

# 原来在没有调用wraps前执行index的函数地址是装饰器的地址,在将装饰器inner函数上面添加@wraps(func)可以将调用的函数地址再返回给原函数

2.迭代器

1.什么是迭代器

迭代器就是指迭代取值的工具,迭代就是指重复反馈过程的活动,每一次对过程的重复就是迭代,而每一次迭代的结果会作为下一次迭代的初始值,单纯的重复不是迭代

2.什么是可迭代对象

凡是内部有.__ iter __()方法的都是可迭代对象,比如序列类型为:str, list, tuple, dict ,set, f(打开的文件). 等

str1.__iter__()
list1 = [1, 2, 3]  # list([1, 2, 3])
list1.__iter__()
set.__iter__()
dict.__iter__()
tuple.__iter__()
open('a.txt').__iter__()

3.什么是迭代器对象

调用obj.__ iter __()方法返回的结果就是一个迭代器对象(Iterator)

 

注意:可迭代对象依赖索引取值,迭代器对象不依赖索引取值

# 依赖索引取值
l1 = [1, 2, 3]
n = 0
while n < len(l1):
   print(l1[n])
   n += 1

# 不依赖索引取值


l1 = [1, 2, 3]
iter_l1 =l1.__iter__()
while True:
print(iter_l1.__next__())
# 当迭代器对象里面的元素被拿就会报错,下面这种方法可以改善

l1 = [1, 2, 3]
iter_l1 =l1.__iter__()

while True:
   try:    # 通过try捕获异常
       print(iter_l1.__next__())

       # 立即触发此处代码 StopIteration
   except StopIteration:
       break

list1 = [1, 2, 3, 4]

for line in list1:  # list1是可迭代对象 ----> 内部会自动调用.__iter__() ---> 迭代器对象--->调用try,except stopiteration,brek等完整的拿到全部数据
   # 迭代器对象.__next__()
   print(line)
# 注意:确定: 迭代器对象也是一个可迭代对象
l1 = [1, 2, 3, 4]
iter_l1 = l1.__iter__()
print(iter_l1.__iter__() is iter_l1)


True
# 可迭代对象不一定是迭代器对象
l1 = [1, 2, 3, 4]
iter_l1 = l1.__iter__()
print(iter_l1 is l1)

False


注意: 唯独文件比较特殊: 因为文件从读取出来的时候就是一个迭代器对象
# f ---> 可迭代对象, 还是迭代器对象
f = open('user.txt', 'r', encoding='utf-8')
# 确定: 文件既是可迭代对象,也是迭代器对象。
# iter_f ---> 迭代器对象
# iter_f = f.__iter__()
print(iter_f is f)  # True

 

4.迭代器对象的优缺点是什么?

优点:1.不依赖于索引迭代取值   2.节省内存空间

缺点:1.取指定某个值麻烦, 每次取值都要从第一个值开始 2.不能len获取长度

posted @ 2019-11-14 00:21  Mr江  阅读(209)  评论(0编辑  收藏  举报