十二、 装饰器迭代器生成器
装饰器本质上来说也是一个函数,其实生成器迭代器也是函数。 这3个器可以让我们编写高效、可重用和可维护的代码。
本章中,目的是了解三个非常有用的工具:装饰器、迭代器和生成器。
12.1 闭包
在学习装饰器之前,首先需要理解一个重要的概念——闭包。闭包是一种函数的特殊现象,是装饰器实现的基础。
闭包是指在一个函数内部定义了另一个函数,并且这个内部函数引用了外部函数中的变量。
当外部函数以内部函数为返回值。
外部函数的作用域(包括其内部的变量)不会被立即销毁,而是保存在内部函数的闭包结构中,使得这些变量在后续调用内部函数时依然可用。
-
一个奇怪的现象
def f(): x = 10 def g(): # 嵌套函数 g print(x) return g # f 函数的返回值是函数 g h = f() # h = g h() # 输出 x=10
- 让我们仔细分析上面的代码:
- 函数
f
内部定义了一个变量x = 10
。 - 函数
f
内部还定义了一个嵌套函数g
,它访问了外部函数f
中的变量x
。 f
函数的返回值是函数g
,所以调用f()
后的结果实际上是g
函数本身。- 将
f()
的返回值赋值给变量h
,即h = g
。 - 调用
h()
实际上是在调用g()
,因此可以顺利打印出x
的值 10。
- 函数
回顾一下函数的生命周期
- 函数作用域生命周期:调用时产生,调用结束时(返回时)销毁
- 也就是说在f() 之后,函数作用域里面的 x=10 应该来说已经被销毁了,不会存在这个变量了。
- 但是往后调用函数h() 依然可以输出x,意味着这边变量似乎被保存下来了。这个现象就是闭包
- 让我们仔细分析上面的代码:
-
闭包现象: 当我们调用
h()
时,尽管f()
已经结束执行并返回,但g()
依然能够访问f()
内部的变量x
。这种外部函数返回后依然保存其作用域内变量的现象就是闭包。 -
总结:闭包 = 内部函数 + 外部函数的环境
闭包可以延长 外部函数的环境作用域
-
案例:以下哪些是闭包?
-
def f(): x = 10 def g(): y = 5 print(y) return g fu = f() fu()
-
def f(x): def g(): print(x+1) return g fu = f() fu()
-
闭包到底什么用?与装饰器什么关系?
闭包在编程中的用途非常广泛,尤其在 Python 中,它们在许多高级编程技术中扮演着重要角色。
-
保持记忆
-
简单例子
def outer_function(x): def inner_function(y): return x + y return inner_function
在这个例子中:
-
outer_function
定义了一个变量x
,并返回了inner_function
。 -
inner_function
使用了外部函数的变量x
,这意味着它“记住”了x
的值,即使outer_function
已经执行完毕。add_five = outer_function(5) # 这里 x 是 5 result = add_five(10) # 这里 y 是 10 print(result) # 输出 15
在这里,
add_five
是一个函数,它记住了x=5
。调用add_five(10)
实际上是inner_function(10)
,结果是5 + 10 = 15
。
通过这个例子,如果把x给他换成一个函数? 让后inner里面去做拓展操作,其实这个就是装饰器
-
-
12.2 装饰器
装饰器是什么?(设计方式) 装饰器是一种用于**“包装”**函数的工具,它可以在不修改原函数代码的情况下,动态地添加功能。装饰器通常使用闭包来实现,因为它需要记住一些上下文(例如,被装饰的函数)并在之后使用。
装饰器本质上是一个高阶函数,它接收一个函数作为参数,并返回一个新的函数(通常是闭包),这个新的函数通常在调用前后会执行一些额外的操作。
-
需求:开发一个foo函数,功能是输出foo
def foo(): print("foo...")
- <