python基础第十七节
17.1 闭包
闭包是指在一个函数内部定义的函数,并且这个内部函数可以访问外部函数的变量、参数。换句话说,闭包是一个包含了函数及其相关引用环境的组合体。
在Python中,当一个函数返回了内部函数的引用时,这个内部函数可以访问并操作外部函数的局部变量,它就创建了一个闭包, 即使外部函数已经执行完毕,它的局部变量仍然可以被内部函数所使用。
闭包的主要特点是可以将数据和行为捆绑在一起,形成一个独立的环境,而不会与其他部分的代码发生冲突。通过闭包,我们可以实现一些高级的编程技巧,如在函数内部创建私有变量、实现函数工厂或装饰器等.
总结:
- 闭包可以保证数据安全.
- 内层函数对外层函数非全局变量的引用, 就会形成闭包.
- 内部函数可以访问外部函数的变量和参数,即使外部函数已经执行完毕。
- 外部函数的局部变量在闭包中被保存,形成了一个私有的环境。
- 闭包可以捕获和保留外部函数的状态信息,使得函数的状态得以保持和更新。
- 被引用到的非全局变量也称自由变量, 这个自由变量会与内层函数产生一个绑定关系
闭包是一种强大的编程技术,它可以使代码更加模块化、可维护和可重用。通过使用闭包,我们可以在函数内部创建和维护状态,而不必依赖全局变量或其他复杂的机制。这使得我们的代码更加清晰、可靠,并且更容易扩展和修改。
案例1: 幂的计算
def power(exponent):
def calculate_power(base):
return base ** exponent
return calculate_power
案例2: 计算每天的平均开销.
案例3: 模拟购物车.
17.2 装饰器
Python装饰器是一种用于修改函数或类行为的特殊函数。它们提供了一种简洁的方式来对现有函数或类进行扩展、修饰或包装,而无需修改它们的源代码。装饰器通常用于在不影响原始函数或类定义的情况下,添加额外的功能或行为。
装饰器本质上是一个函数,它接受一个函数作为输入,并返回一个新的函数。装饰器函数通常在内部定义一个闭包函数,用于包装原始函数,添加额外的逻辑或功能。装饰器函数可以访问原始函数的参数和返回值,并可以在调用前后执行自定义的操作.
装饰器提供了一种简洁而灵活的方式来修改函数的功能,使得我们可以在不改变原代码的情况下添加额外的功能. 用一句话来说就是: 装饰器就是创建一个闭包函数, 在闭包函数的内部调用目标函数, 然后添加相应的功能.
装饰器的语法:
在Python中,装饰器是通过使用@符号来应用的。它可以直接放在函数的定义之前,用于修饰该函数。以下是装饰器的基本语法:
@decorator
def func():
# 函数定义和实现
pass
装饰器的应用场景:
装饰器在实际开发中有许多应用场景,以下是一些常见的例子:
- 添加日志:可以使用装饰器在函数调用前后记录日志信息,方便调试和追踪问题。
- 计时器:可以使用装饰器来测量函数的执行时间,用于性能分析和优化。
- 缓存:可以使用装饰器来缓存函数的结果,提高重复调用时的性能。
- 权限验证:可以使用装饰器来验证用户的身份和权限,实现访问控制。
- 输入验证:可以使用装饰器来验证函数的输入参数,确保其符合要求。
注意事项:
在使用装饰器时,需要注意以下几点: - 装饰器只会在被装饰函数定义时执行一次,而不会在每次函数调用时执行。
- 装饰器的顺序很重要,多个装饰器的执行顺序是从上到下的。
17.3 生成器
生成器
生成器是一种特殊类型的函数,可以按需生成一系列的值,而不是一次性将所有值都计算出来并存储在内存中。生成器可以大大节省内存消耗,特别适用于处理大型数据集或无限序列。
yield语句
生成器函数是一种定义生成器的方法。它使用关键字yield来定义生成器的每个值。当生成器函数被调用时,它不会立即执行函数体的所有代码,而是在每次调用生成器的__next__()方法时执行一部分代码,并在遇到yield语句时返回一个值。yield 和 return 是在 Python 中用于返回值的两个关键字,它们在功能和用法上有一些区别。
return关键字用于函数内部,用于将值从函数中返回给调用者,并终止函数的执行。在函数中执行return后,函数将立即结束,并返回指定的值。函数只能使用return返回一次,并且返回的值可以被接收并使用。yield关键字用于生成器函数中,用于定义一个生成器函数,并将值产生给调用者。生成器函数是一种特殊的函数,可以通过yield关键字将多个值逐步产生,而不是一次性返回所有结果。当生成器函数执行到yield语句时,函数会暂停执行并将值返回给调用者,但函数的状态会被保存,以便下次从暂停的地方继续执行。生成器函数可以多次使用yield来生成多个值,并且可以在需要时进行迭代处理。
总结区别:return用于函数中,一次性返回最终结果并终止函数的执行。yield用于生成器函数中,逐步产生值并暂停函数的执行,可以多次使用,并且在需要时进行迭代处理。
案例: 编写一个包含斐波那契数列的生成器.
使用生成器
生成器通过next()函数或迭代语句来逐个获取生成器的值。生成器会记录它的内部状态,因此每次调用next()函数时会从上次停止的地方继续执行。
生成器表达式
生成器表达式是一种简洁的语法,用于快速创建生成器。它的语法与列表推导式类似,但使用圆括号而不是方括号。生成器表达式可以在需要时逐个生成值,而不是一次性生成所有值。
下面是一个生成器表达式的示例,它生成了一个包含1到10之间所有偶数的生成器:
even_numbers = (x for x in range(1, 11) if x % 2 == 0)
生成器的优势
使用生成器有以下几个优势:
- 节省内存消耗:生成器按需生成值,而不需要一次性生成所有值,可以节省大量内存消耗,尤其适用于处理大型数据集或无限序列。
- 惰性计算:生成器在需要时逐个生成值,可以提供惰性计算的能力,避免不必要的计算。
- 无限序列:生成器可以轻松地表示无限序列,如斐波那契数列或素数序列,而无需事先计算所有值。
- 迭代器的统一接口:生成器实现了迭代器协议,可以使用相同的方式处理生成器和其他迭代器。
生成器是Python中非常强大和灵活的工具,可以优化代码的性能和内存消耗,并简化处理大型数据集和无限序列的操作。通过掌握生成器的概念和使用方法,可以提高代码的效率和可读性.
生成器的工作原理
生成器的工作原理是通过迭代器协议来实现的。生成器函数使用yield语句将值生成出来,并在生成值后暂停执行,将控制权交还给调用者。当调用者请求下一个值时,生成器函数会从上次暂停的地方继续执行,生成下一个值,并再次暂停。
这种逐步生成值的方式使得生成器可以有效地处理大量的数据或无限的序列,而不会一次性占用大量的内存空间。