【python高级用法】迭代器、生成器、装饰器、闭包

这篇具有很好参考价值的文章主要介绍了【python高级用法】迭代器、生成器、装饰器、闭包。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

迭代器

  • 可迭代对象:可以使用for循环来遍历的,可以使用isinstance()来测试。

  • 迭代器:同时实现了__iter__()方法和__next__()方法,可以使用isinstance()方法来测试是否是迭代器对象


from collections.abc import Iterable, Iterator
li = [11, 22, 33, 44, 55]

print(isinstance(li, Iterable)
iterator_li = iter(li)
print(isinstance(iterator_li, Iterator)

使用类实现迭代器

两个类实现一个迭代器


class MyList(object):
    """自定义的一个可迭代对象"""
    def __init__(self):
        self.items = []

    def add(self, val):
        self.items.append(val)

    def __iter__(self):
        #python中万物皆对象,将该类对象的引用self作为实参传入到MyIterator类中
        myiterator = MyIterator(self)
        return myiterator


class MyIterator(object):
    """自定义的供上面可迭代对象使用的一个迭代器"""
    #这里的mylist就MyList对象
    def __init__(self, mylist):
        self.mylist = mylist
        # current用来记录当前访问到的位置
        #每一次调用for循环时,索引位置都从零开始
        self.current = 0

    def __next__(self):
        if self.current < len(self.mylist.items):
            item = self.mylist.items[self.current]
            self.current += 1
            return item
        else:
            raise StopIteration

    def __iter__(self):
        return self

一个类实现迭代器


class MyList(object):
    """自定义的一个可迭代对象"""
    def __init__(self):
        self.items = []
        self.current = 0

    def add(self, val):
        self.items.append(val)

    def __iter__(self):
        #返回自身引用,自己本身就是一个迭代器对象
        return self

    def __next__(self):
        if self.current < len(self.items):
            item = self.items[self.current]
            self.current += 1
            return item
        else:
            #使用for循环第二次遍历时,self.current可以从0开始
            self.current = 0
            raise StopIteration
  • 可迭代对象与迭代器的总结

  1. 一个具备了__iter__方法的对象,就是一个可迭代对象

  1. 当对一个可迭代对象调用iter()函数时,它会自动调用这个可迭代对象的__iter__方法,这个方法返回的对象当作迭代器

  1. 当对一个迭代器对象调用next()函数时,他会自动调用这个迭代器对象的__next__方法,这个方法返回想要的数据

  1. 迭代器一定是可迭代对象,可迭代对象不一定是迭代器

  1. 数据类型list、dict、str等是Iterable单不是Iterator,不过可以通过iter()函数获得一个Iterator对象

  • 迭代器的应用

  1. 如果每次返回的数据值不是在一个已有的数据集合中,而是通过程序按照一定的规律计算生成的,那就不用再依赖一个已有的数据集合,也就是说不用再将所有要迭代的数据都一次性缓存下来,这样可以节省大量的存储(内存)空间。


class FeiboIterator(object):
    """斐波那契数列迭代器"""
 
    def __init__(self, n):
        # 斐波那数列值的个数
        self.n = n
        # 记录当前遍历的下标
        self.index = 0
        # 斐波那数列前面的两个值
        self.num1 = 0
        self.num2 = 1
 
    def __next__(self):
        """被next()函数调用来获取下一个数"""
        if self.index < self.n:
            num = self.num1
            self.num1, self.num2 = self.num2, self.num1 + self.num2
            self.index += 1
            return num
        else:
            raise StopIteration
 
    def __iter__(self):
        """迭代器的__iter__返回自身即可"""
        return self
 
 
if __name__ == '__main__':
    fb = FeiboIterator(20)
    for num in fb:
        print(num, end=' ')

生成器

生成器的定义

  1. 使用了yield关键字的函数不再是函数,而是生成器。

  1. yield关键字有两点作用:

  • 保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起

  • 将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return作用

  1. 可以使用next()函数让生成器从断点处继续执行,唤醒生成器(函数)

  1. python3中的生成器可以使用return返回最终运行的返回值

  1. 生成器是这样一个函数,他记住上一次返回在函数体中的位置。对生成器函数的第二次(或第n次)调用跳转至函数中间,而上次调用的所有的局部变量都保持不变。生成器不仅记住了他的数据状态,生成器还记住了它在流程控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

  1. 生成器的特点:

  • 存储的是生成数据的方式(即算法),而不是存储生成的数据,因此节约内存。

生成器的使用


def create_points():
    k = 2
    b = 1
    x = 0
    while True:
        y = k * x + b
        #当使用send方法时,会将send方法中的参数赋给temp,send()方法与next()方法类似,都可以取生成器中的下一个元素。
        temp = yield (x,y)
        if temp:
            k, b = temp
        x = y

if __name__ == '__main__':
    #不再是一个普通函数的调用,因为函数体内包含yield关键字,此时是生成一个生成器对象
    g = create_points()
    # print(next(g))
    # print(next(g))
    # print(g.send((3, 4)))
    # print(next(g))
    # print(next(g))
    count = 0
    for i in g:
        if count > 3:
            break
        print(i)
        count += 1
【python高级用法】迭代器、生成器、装饰器、闭包,python,开发语言

参考链接:

python生成器的原理和业务场景下的使用_for line in tqdm(f, desc='read sentence_cuts'):如果不-CSDN博客

装饰器

装饰器的定义

装饰器可以在不改变某函数结构和调用方式基础之上,为其增加新的功能,并且最大化复用新的功能。

装饰器的应用场景

为函数增加日志记录、登录校验、权限校验等,我们可以将这些功能写成一个装饰器,然后直接应用到相应需要改功能的函数中即可,可以保证对原代码和函数零侵入。

装饰器的本质是一个闭包函数

  • 装饰器函数
def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"{func.__name__} cost time: {execution_time:.4f} s")
        return result
    return wrapper
  • 构造执行函数
@timing_decorator
def demo():
    time.sleep(5)
    

执行demo函数时,会打印该函数执行时间为5s

参考文献:

python装饰器全解--包含实现原理及应用场景_装饰器实现原理-CSDN博客

闭包

什么是闭包

概念:一个函数可以引用作用域外的变量,同时也可以在函数内部进行使用的函数,称之为闭包函数。而这个作用域外的变量,称之为自由变量。这个自由变量不同于C++的static修饰的静态变量,也不同于全局变量,它是和闭包函数进行绑定的。

  1. 闭包函数是函数的嵌套,函数内还有函数,即外层函数嵌套一个内层函数

  1. 在外层函数定义局部变量,在内层函数通过nonlocal引用,并实现指定功能,比如计数

  1. 最后外层函数return内层函数

  1. 主要作用:可以变相实现私有变量的功能,即用内层函数访问外层函数内的变量,并让外层函数内的变量常驻内存

为什么要使用闭包

  1. 封装变量: 闭包允许你创建一个包含函数和其所在环境中变量的封闭空间。这样,你可以隐藏一些变量,使其不易被外部访问,起到一定的封装作用。

  2. 保持状态: 闭包函数可以保持其创建时的状态。这意味着你可以在函数外部改变闭包内部的变量,并且在多次调用闭包时保持这些变量的状态。

  3. 函数工厂: 闭包函数可以用作函数工厂,动态生成函数。这对于根据不同情况生成不同行为的场景很有用。

  4. 实现装饰器: 闭包函数常用于实现装饰器模式,通过在函数外层包装其他函数来增强其功能,而无需修改原始函数的代码。

  5. 实现私有变量和方法: 通过闭包,你可以模拟出类似于面向对象编程中的私有变量和方法,限制对内部实现的访问。

闭包的应用场景是什么

创建一个计数器,但又不想让外部直接访问计数变量

def create_counter():
    count = 0  # 这个变量在闭包内

    def counter():
        nonlocal count  # 使用 nonlocal 关键字声明 count 不是局部变量
        count += 1
        return count

    return counter

# 创建一个计数器
my_counter = create_counter()

# 使用计数器
print(my_counter())  # 输出 1
print(my_counter())  # 输出 2
print(my_counter())  # 输出 3

在这个例子中,create_counter 函数返回了一个内部定义的 counter 函数count 变量被封装在 counter 函数的闭包中,因此外部无法直接访问。每次调用 my_counter() 时,计数器会递增并返回当前计数值。

这样做的好处是,我们可以创建多个独立的计数器,它们各自维护自己的状态,而不会互相干扰。闭包在这里提供了一种轻量级的状态封装和隔离的机制。文章来源地址https://www.toymoban.com/news/detail-769006.html

到了这里,关于【python高级用法】迭代器、生成器、装饰器、闭包的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python迭代器与生成器研究记录

    迭代器肯定是可迭代对象,但是可迭代对象不一定是迭代器,生成器一定是迭代器,但是迭代器不一定是生成器 生成器是特殊的迭代器,所以生成器一定是迭代器,迭代器一定是可迭代对象 我们平常接触最多的对象中,字符串,字典,列表,集合,元组和open打开的文件对象

    2024年02月05日
    浏览(47)
  • 8 python的迭代器和生成器

    概述         在上一节,我们介绍了Python的模块和包,包括:什么是模块、导入模块、自定义模块、__name__、什么是包、创建包、导入包等内容。在这一节中,我们将介绍Python的迭代器和生成器。在Python中,迭代器是一个非常重要的概念,它使得我们能够遍历一个序列而无

    2024年02月10日
    浏览(33)
  • 3.0 Python 迭代器与生成器

    当我们需要处理一个大量的数据集合时,一次性将其全部读入内存并处理可能会导致内存溢出。此时,我们可以采用迭代器 Iterator 和生成器 Generator 的方法,逐个地处理数据,从而避免内存溢出的问题。 迭代器是一个可以逐个访问元素的对象,它实现了 python 的迭代协议,即

    2024年02月13日
    浏览(35)
  • Python基础篇(十):迭代器与生成器

    迭代器和生成器是Python中用于 处理可迭代对象 的重要概念。它们提供了一种有效的方式来 遍历和访问 集合中的元素,同时具有 节省内存和惰性计算 的特点。下面是关于迭代器和生成器的详细介绍和示例: 迭代器是一种实现了迭代协议的对象,它可以用于遍历集合中的元素

    2024年02月10日
    浏览(35)
  • Python教程(26)——Python迭代器和生成器详解

    Python中的迭代器是一种对象,它可以迭代(遍历)一个可迭代对象(比如列表、元组或字符串)的元素。迭代器用于实现迭代器协议,即包含 __iter__() 方法和 __next__() 方法。 迭代器的工作原理是每次调用 __next__() 方法时返回可迭代对象的下一个元素,当没有元素可迭代时,抛

    2024年02月19日
    浏览(38)
  • Python小姿势 - ## Python中的迭代器与生成器

    Python中的迭代器与生成器 在Python中,迭代是一个非常重要的概念,迭代器和生成器是迭代的两种最常见的形式。那么,迭代器与生成器有何不同呢? 首先,我们先来了解一下迭代器。 迭代器是一种对象,它可以记住遍历的位置,并在每次访问时返回下一个元素。迭代器只能

    2024年02月04日
    浏览(46)
  • 【Python 4】列表与元组slice切片 迭代 列表生成式 生成器generator 迭代器Iterator对象

    在Python中,代码不是越多越好,而是越少越好 取一个list或tuple的部分元素是非常常见的操作 对这种经常取指定索引范围的操作,用循环十分繁琐,因此,Python提供了切片(Slice)操作符,能大大简化这种操作 L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3 如果第

    2024年02月07日
    浏览(44)
  • python使用迭代生成器yield减少内存占用的方法

    在python编码中for循环处理任务时,会将所有的待遍历参量加载到内存中。 其实这本没有必要,因为这些参量很有可能是一次性使用的,甚至很多场景下这些参量是不需要同时存储在内存中的,这时候就会用到本文所介绍的迭代生成器yield。 首先我们用一个例子来演示一下迭代

    2024年04月28日
    浏览(26)
  • Python黑魔法:探秘生成器和迭代器的神奇力量

    在Python中,生成器和迭代器是实现惰性计算的两种重要工具,它们可以帮助我们更有效地处理数据,特别是在处理大数据集时,可以显著减少内存的使用。接下来,我们将详细介绍这两种工具。 迭代器是一种特殊的对象,它可以遍历一个集合中的所有元素。任何实现了__ite

    2024年02月12日
    浏览(42)
  • 【Python】Python系列教程-- Python3 迭代器与生成器(二十)

    往期回顾: Python系列教程–Python3介绍(一) Python系列教程–Python3 环境搭建(二) Python系列教程–Python3 VScode(三) Python系列教程–Python3 基础语法(四) Python系列教程–Python3 基本数据类型(五) Python系列教程-- Python3 数据类型转换(六) Python系列教程-- Python3 推导式(

    2024年02月08日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包