闭包函数与迭代器生成器 闭包函数 迭代器 生成器

闭包函数定义

  • 必须是函数内嵌函数

  • 内嵌函数必须引用外函数的变量

  • 外函数返回内嵌函数的函数名

def otter():
    name = 'Gredae'
    def inner():  # 外层函数包了个内层函数
        print(name)  # 内层函数引用了外层函数的变量
    return inner  # 外层函数返回内层函数的函数名
f = otter()  # 用f变量来接收inner函数的地址
f()  # 实际上是调用inner()函数

闭包函数的作用

可以使用函数闭包来实现一个函数的装饰器

函数装饰器的条件

  1. 不能改变原来函数的代码
  2. 为函数添加新的功能
  3. 不能改变函数的调用方式

装饰器的简单使用

计算函数运行的时间:

import time
def deco(func):  # func = index
    """装饰器函数"""
    def inner():
        start = time.time()
        func()  # index
        end = time.time()
        print(end - start)
    return inner
@deco  # 如果在被装饰的函数上方写了语法糖就可以代替下面的 index = deco(index)
def index():
    """被装饰的函数"""
    time.sleep(1)
    print('hello, index')

index = deco(index)  # index = inner 如果上面写了@deco语法糖就可以代替这一行
index()  # 实际上执行的是inner函数

上面的是双层装饰器

三层装饰器饰装饰装饰器

def auth(engine):
    def login(func):
        def inner(*args, **kwargs):  #将可变长参数传递进来
            # 登录功能
            if engine == 'file':
                username = input('usrename:')
                pwd = input('pwd:')
                if username == 'Gredae' and pwd == '123':
                    print('登录成功')
                    res = func(*args, **kwargs)  #传递不定长实参
                    return res
                else:
                    print('登录失败')

            elif engine == 'db':
                print('账号密码来自于数据库,非法请求')

        return inner
    return login

@auth('file')  # 三层装饰可以使用语法糖来传值
def login():
    print('欢迎你!')

login() # inner()

迭代器

更新换代, 重复, 基于上一次的结果推出下一次的结果

迭代:具有__iter__方法

可迭代 不可迭代
字符串、列表、字典、元祖、集合、文件 数值对象、函数

例如:

s = 'Gredae'
s_iter = s.__iter__()
print(s_iter.__next__())  # G  ## 基于索引(基于上一次结果)通过__next__进行迭代
print(s_iter.__next__())  # r
print(s_iter.__next__())  # e
print(s_iter.__next__())  # d

迭代器对象:具有__iter__以及__next__方法

迭代对象除了文件是迭代对象之外都不属于迭代对象

迭代循环——for循环(解决了不依赖索引取值)

lt = [1,2,3,4]
lt_iter = lt.__iter__()  ## 也可以这样定义迭代对象: lt_iter = iter(lt)
while True:
    try:
        print(lt_iter.__next__())  ##这句话一定会报错 也可以这样迭代: next(lt_iter)
    except StopIteration:  ## 当lt_iter迭代到没有元素的时候就会报错
        break
for i in lt:   # 可迭代对象;迭代器对象  # 不依赖索引取值,而是迭代取值
    print(i)
  1. 首先使用iter把lt变成迭代器对象;对于文件也要使用iter方法吧文件再一次iter下
  2. 然后使用next方法进行迭代取值
  3. 判断StopIteration异常,遇到异常终止

迭代器对象一定是可迭代对象; 可迭代对象不一定是迭代器对象

生成器

在 Python 中,使用了 yield 的函数被称为生成器(generator)

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器

在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

例如,可以使用生成器生成一个斐波那契数列

def fibonacci(n):  # 生成器函数 - 斐波那契
    '''生成斐波那契'''
    a, b, counter = 1, 1, 0
    while counter < n:
        yield a
        a, b = b, a + b
        counter += 1
        
f = fibonacci(10)  # f 是一个迭代器,由生成器返回生成
while True:
    try:
        print(next(f), end=" ")
    except StopIteration:
        break