zoukankan      html  css  js  c++  java
  • 闭包函数与迭代器生成器

    闭包函数

    闭包函数定义

    • 必须是函数内嵌函数

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

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

    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
    
  • 相关阅读:
    Solution: Win 10 和 Ubuntu 16.04 LTS双系统, Win 10 不能从grub启动
    在Ubuntu上如何往fcitx里添加输入法
    LaTeX 笔记---Q&A
    Hong Kong Regional Online Preliminary 2016 C. Classrooms
    Codeforces 711E ZS and The Birthday Paradox
    poj 2342 anniversary party
    poj 1088 滑雪
    poj 2479 maximum sum
    poj 2481 cows
    poj 2352 stars
  • 原文地址:https://www.cnblogs.com/Gredae/p/11348021.html
Copyright © 2011-2022 走看看