欢迎光临
我们一直在努力

Python的函数式编程: 闭包与装饰器

1. 闭包 (Closure)

核心概念

闭包并非 Python 独有,Scala 中也有。 简单来说:闭包 = 函数 + 该函数定义时的环境(上下文变量)。

这就好比 Spark 中,你在 Driver 端定义了一个变量,然后在 RDD 的 map 算子中使用它。Spark 会把这个变量序列化并“打包”发送到各个 Executor 节点上。这个“打包带走”的动作,就是闭包的核心逻辑。

Python 代码实战

Python 的函数是“一等公民”(First-class citizen),可以嵌套定义。

def make_normalizer(mean, std):
   # — 外部环境 (Environment) —
   # 这两个变量被内部函数\”捕获\”了
 
   def normalize(x):
       # — 核心逻辑 (Code) —
       # 即使 make_normalizer 已经执行完毕返回了,
       # normalize 依然记得 mean 和 std 的值
       return (x – mean) / std
 
   return normalize

# 创建一个针对 ImageNet 数据的归一化函数
# 此时,mean 和 std 被\”封印\”在了 func 对象的 __closure__ 属性中
imagenet_norm = make_normalizer(mean=0.485, std=0.229)

# 像调用普通函数一样调用
print(imagenet_norm(0.5))

# 【硬核视角】大数据开发者喜欢看底层:
# 我们可以查看闭包里到底存了什么
print(imagenet_norm.__closure__[0].cell_contents) # 输出 0.485 (mean)

❗ Java/Scala 差异点 (Diff):

  • Java: 匿名内部类或 Lambda 也可以访问外部变量,但要求变量必须是 final 或 effectively final(不可变)。

  • Python: 只有 nonlocal 关键字限制。你可以读取外部变量;如果你想修改闭包内的外部变量(比如计数器),需要在内部函数声明 nonlocal count。

  • Scala: Scala 的闭包行为和 Python 非常像,都是通过捕获引用实现的。

关键字Nonlocal

Nonlocal关键字修饰闭包内层的函数时, 使其可以改变外层函数的变量引用.

在 Python 中,使用规则可以总结为一句话:读(Read)和修改内部(Mutate)不需要声明,重指向(Reassign)必须声明。

1. 什么时候【不需要】nonlocal?

这是最常见的情况。只要你不使用赋值符号 = 修改变量本身的指向,就不需要。

情况 A:只是“读取”外部变量

Python 遵循 LEGB 规则(Local -> Enclosing -> Global -> Built-in)。它会自动向外查找。

def outer():
   x = 100
 
   

赞(0)
未经允许不得转载:171主机测评 » Python的函数式编程: 闭包与装饰器
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址