Python 学习笔记-第13讲:面向对象-迭代器与闭包

本文介绍了Python中的迭代器概念,包括其实现原理及其在不同数据结构中的应用,特别是其在处理大型数据集时的优势。此外,文章还深入探讨了闭包的概念及LEGB法则,解释了闭包如何在函数执行环境中捕获变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、迭代器

将某个数据集内的数据逐个取出的过程叫做迭代。字符串、列表、元组、字典、集合都可以使用 for 遍历访问,它们都是可迭代对象。

迭代器是访问集合内元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问一遍后结束。

迭代器不能回退,只能往前进行迭代。

对于原生支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值,这是后话)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
迭代器的另一个优点就是它不要求你事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。这个特点被称为延迟计算或惰性求值(Lazy evaluation)。

迭代器更大的功劳是提供了一个统一的访问集合的接口。只要是实现了__iter__()方法的对象,就可以使用迭代器进行访问。

可以直接作用于for循环的对象统称为可迭代对象(Iterable)。
可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。


所有的Iterable均可以通过内置函数iter()来转变为Iterator。

迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
对迭代器来讲,有一个__next__()就够了。在你使用for 和 in 语句时,程序就会自动调用即将被处理的对象的迭代器对象,然后使用它的__next__()方法,直到监测到一个StopIteration异常。
实际上,因为迭代操作如此普遍,Python专门将关键字for用作了迭代器的语法糖。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。上述代码可以写成如下的形式,你一定非常熟悉:

for val in lst: print val

首先Python将对关键字in后的对象调用iter函数获取迭代器,然后调用迭代器的next方法获取元素,直到抛出StopIteration异常。对迭代器调用iter函数时将返回迭代器自身,所以迭代器也可以用于for语句中,不需要特殊处理。

for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了

for val in lst: print val
使用迭代器的循环可以避开索引,但有时候我们还是需要索引来进行一些操作的。这时候内建函数enumerate就派上用场咯,它能在iter函数的结果前加上索引,以元组返回,用起来就像这样:

for idx, ele in enumerate(lst):
    print idx, ele

优秀博文:

http://www.cnblogs.com/Eva-J/articles/7213953.html


二、闭包

“在Python中,函数本身也是对象”

1. 函数是第一类对象
和list, tuple, dict以及用House创建的对象一样,当你定义一个函数时,函数也是对象:
def func(a, b):
    return a+b
 
在全局域,函数对象被函数名引用着,它接收两个参数a和b,计算这两个参数的和作为返回值。
所谓第一类对象,意思是可以用标识符给对象命名,并且对象可以被当作数据处理,例如赋值、作为参数传递给函数,或者作为返回值return 等


因此,你完全可以用其他变量名引用这个函数对象:
add = func
 
这样,你就可以像调用func(1, 2)一样,通过新的引用调用函数了:


print func(1, 2)
print add(1, 2)  #the same as func(1, 2)
 
或者将函数对象作为参数,传递给另一个函数:
def caller_func(f):
    return f(1, 2)
if __name__ == "__main__":
    print caller_func(func)


2. 函数对象 vs 函数调用
无论是把函数赋值给新的标识符,还是作为参数传递给新的函数,针对的都是函数对象本身,而不是函数的调用。


3. 闭包&LEGB法则

所谓闭包,就是将组成函数的语句和这些语句的执行环境打包在一起时,得到的对象

解析器按照下面的顺序查找filename变量:
• Local - 本地函数(show_filename)内部,通过任何方式赋值的,而且没有被global关键字声明为全局变量的filename变量;
• Enclosing - 直接外围空间(上层函数wrapper)的本地作用域,查找filename变量(如果有多层嵌套,则由内而外逐层查找,直至最外层的函数);
• Global - 全局空间(模块enclosed.py),在模块顶层赋值的filename变量;
• Builtin - 内置模块(__builtin__)中预定义的变量名中查找filename变量;
在任何一层先找到了符合要求的filename变量,则不再向更外层查找。如果直到Builtin层仍然没有找到符合要求的变量,则抛出NameError异常。这就是变量名解析的:LEGB法则。
总结:
. 闭包最重要的使用价值在于:封存函数执行的上下文环境;
. 闭包在其捕捉的执行环境(def语句块所在上下文)中,也遵循LEGB规则逐层查找,直至找到符合要求的变量,或者抛出异常。


for val in lst: print val

标题基于PHP + JavaScript的助眠小程序设计实现AI更换标题第1章引言介绍助眠小程序的研究背景、意义,以及论文的研究内容和创新点。1.1研究背景意义阐述助眠小程序在当前社会的重要性和应用价值。1.2国内外研究现状分析国内外在助眠小程序方面的研究进展及现状。1.3论文研究内容创新点概述论文的主要研究内容和创新之处。第2章相关理论基础介绍助眠小程序设计实现所涉及的相关理论基础。2.1PHP编程技术阐述PHP编程技术的基本概念、特点和在助眠小程序中的应用。2.2JavaScript编程技术介绍JavaScript编程技术的核心思想、作用及在小程序中的实现方式。2.3小程序设计原理解小程序的设计原则、架构和关键技术。第3章助眠小程序需求分析对助眠小程序进行详细的需求分析,为后续设计实现奠定基础。3.1用户需求调研用户需求调研的过程和方法,总结用户需求。3.2功能需求分析根据用户需求,分析并确定助眠小程序的核心功能和辅助功能。3.3性能需求分析明确助眠小程序在性能方面的要求,如响应速度、稳定性等。第4章助眠小程序设计详细阐述助眠小程序的设计方案,包括整体架构、功能模块和界面设计。4.1整体架构设计给出助眠小程序的整体架构设计思路和实现方案。4.2功能模块设计详细介绍各个功能模块的设计思路和实现方法。4.3界面设计阐述助眠小程序的界面设计风格、布局和交互设计。第5章助眠小程序实现测试解助眠小程序的实现过程,并进行详细的测试分析。5.1开发环境搭建配置介绍开发环境的搭建过程和相关配置信息。5.2代码实现优化详细阐述助眠小程序的代码实现过程,包括关键技术的运用和优化措施。5.3测试性能分析对助眠小程序进行全面的测试,包括功能测试、性能测试等,并分析测试结果。第6章结论展望总结论文的研究成果,展望未来的研究方向和应用前景。6.1研究成果总结概括性地总结论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值