# 复习
# 闭包函数——在内部函数使用外部函数的变量
#
# 装饰器函数——装饰器一定是闭包函数
# 装饰器的作用:在不改变原来函数的调用方式的情况下,在这个函数的前后添加新功能
# 开放封闭原则:对扩展开放,对修改封闭
# 基础的装饰器
# def wrapper(f):
# @wraps(f)
# def inner(*args,**kwargs):
# '''这里是在函数执行前添加的代码'''
# ret = f(*args,**kwargs) # f是被装饰的函数 在这里被调用
# '''这是函数执行后添加的代码'''
# return ret
# return inner()
# @wrapper:使用装饰器
# 完美的装饰器
# from functools import wraps
# @wraps(f) # 获取原来的装饰器的名字
# 带参数的装饰器
# @wrapper --> @wrapper(argument)
# 三层非嵌套,
# def outer(形参):
# def wrapper(f):
# def inner(*args,**kwargs):
# '''这里是在函数执行前添加的代码'''
# ret = f(*args,**kwargs) # f是被装饰的函数 在这里被调用
# '''这是函数执行后添加的代码'''
# return ret
# return inner()
# return wrapper
# @wrapper
# def f(实参)
# pass
# # 多个装饰器装饰一个函数:执行顺序wrapper3,wrapper2,wrapper1
# @wrapper1
# @wrapper2
# @wrapper3
# def f():
# pass
# 迭代器
# 索引
# 循环 for
# print(dir([])) # 返回所有方法
# ret = set(dir([]))&set(dir(''))&set(dir(range(10))) # 转化成 集合然后求交集
# print(ret)
# print('__iter__' in dir(int))# False
# print('__iter__' in dir(str))
# print('__iter__' in dir(bool))# False
# print('__iter__' in dir(dict))
# print('__iter__' in dir(set))
# print('__iter__' in dir(tuple))
# print('__iter__' in dir(enumerate))
# print('__iter__' in dir(range(1)))
# # 只要是能被for循环的数据类型,就一定拥有__iter__方法
# print([].__iter__()) # <list_iterator object at 0x104102470>
# print([1,2,3].__iter__().__length_hint__()) # 元素个数:3
# 一个列表执行了__iter__()之后的返回值就是一个迭代器
# l = [1,2,3]
# iterator = l.__iter__()
# print(iterator.__next__()) # 1
# print(iterator.__next__()) # 2
# print(iterator.__next__()) # 3
# print(iterator.__next__()) # 报错
# Iterable 可迭代的 -- > __iter__ 只要含有__iter__方法的都是可以迭代的,都可以被for循环
# [].__iter__()迭代器 -- > __next__ 通过next方式可以从迭代器中一个一个取值
# 只要含有__iter__方法的都是可以迭代的——可迭代协议
# 迭代器协议——内部含有__next__和__iter__方法的就是迭代器
# print('__iter__' in dir([].__iter__()))
# # 列表可迭代,但不是一个迭代器
# from collections import Iterable
# from collections import Iterator
# print(isinstance([],Iterator)) # False
# print(isinstance([],Iterable)) # True
# 迭代器协议和可迭代协议
# 可以被for循环的都是可迭代的
# 可迭代的内部都有__iter__方法
# 迭代器一定可迭代
# 可迭代的代用__iter__就可以得到一个迭代器
# 迭代器中的一个__next__方法可以一个一个的获取值
# for循环其实就是在使用迭代器
# 判断是否是迭代器:
# for
# 只有是可迭代对象的时候才能使用for
# 当遇到一个新的变量,斌呢过确定是否可以使用for循环,就判断是否可迭代
# 内部是否有__iter__()方法 (__iter__() in dir(巴拉巴拉))
# for i in l:
# Pass
# iterator = l.__iter__()
# iterator.__next__()
# 迭代器的好处:
# 从容器类型中一个一个的取值,会把所有的值都取到
# 节省内存空间:对于迭代器并不会在内存中再占用一大块内存,而是随着循环 每次生成一个/每次nect每次提供一个
# # 不使用for循环实现
# l = [1,2,3,4,5]
# iterator = l.__iter__()
# while True:
# print(iterator.__next__())
# 生成器——本质:迭代器
# 生成器函数——本质我们自己写的函数
# 生成器表达式
# 只要含有yield关键字的函数都是生成器函数
# yield 和 return 不能共用,且需要写在函数内部
# def generator():
# print(1)
# yield 'a'
# # 生成器函数:执行之后会得到一个生成器作为返回值
# ret = generator()
# print(ret)# <generator object generator at 0x10410d0f8>
# # ret.__next__
# # ret.__iter__
# print(ret.__next__())
# def generator():
# print(1)
# yield 'a'
# print(2)
# yield 'b'
# g = generator()
# print(g.__next__())# 1 a
# print(g.__next__())# 2 b
# print(g.__next__())# 报错
# for i in g: # 1 a 2 b
# print(i)
# 娃哈哈%i
# def test_wahaha():
# for i in range(20):
# yield 'wahaha{}'.format(i)
#
# g = test_wahaha()
# for i in g:
# print(i)
# 监听文件的输入
# def func(filename):
# f = open(filename,encoding='UTF-8')
# while True:
# line = f.readline()
# if line.strip():
# # print('****',line.strip())
# yield line.strip()
#
# g = func('file')
# for i in g:
# if 'python' in i:
# print('---'+i)