python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python函数作用域与闭包

Python函数作用域与闭包举例深度解析

作者:韩公子的Linux大集市

Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,这篇文章主要介绍了Python函数作用域与闭包的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

1. 基础作用域访问

示例1:访问全局变量

global_var = "全局变量"

def access_global():
    print(f"函数内部访问: {global_var}")

access_global()  # 输出: 函数内部访问: 全局变量
print(f"函数外部访问: {global_var}")  # 输出: 函数外部访问: 全局变量

解析

示例2:访问外层函数变量

def outer():
    outer_var = "外层变量"
    
    def inner():
        print(f"内部函数访问: {outer_var}")
    
    inner()

outer()  # 输出: 内部函数访问: 外层变量

解析

2. 闭包基础

示例3:简单闭包

def create_counter():
    count = 0
    
    def counter():
        nonlocal count  # 声明使用外层变量
        count += 1
        return count
    
    return counter

counter1 = create_counter()
print(counter1())  # 输出: 1
print(counter1())  # 输出: 2

counter2 = create_counter()
print(counter2())  # 输出: 1

解析

示例4:带参数的闭包

def power_factory(exponent):
    def power(base):
        return base ** exponent
    return power

square = power_factory(2)
cube = power_factory(3)

print(square(5))  # 输出: 25
print(cube(5))    # 输出: 125

解析

3. 闭包的高级应用

示例5:状态保持

def create_bank_account():
    balance = 0
    
    def deposit(amount):
        nonlocal balance
        balance += amount
        return balance
    
    def withdraw(amount):
        nonlocal balance
        if amount > balance:
            return "余额不足"
        balance -= amount
        return balance
    
    def get_balance():
        return balance
    
    return deposit, withdraw, get_balance

deposit, withdraw, get_balance = create_bank_account()

print(deposit(100))  # 输出: 100
print(withdraw(30))   # 输出: 70
print(get_balance())  # 输出: 70

解析

示例6:回调函数

def event_handler(event_name):
    def handler(callback):
        print(f"处理事件: {event_name}")
        callback()
    return handler

button_click = event_handler("按钮点击")

def log_action():
    print("执行点击操作")

button_click(log_action)
# 输出:
# 处理事件: 按钮点击
# 执行点击操作

解析

4. 作用域链与LEGB规则

示例7:多层嵌套作用域

x = "全局变量"

def outer():
    x = "outer变量"
    
    def inner():
        x = "inner变量"
        print(f"最内层: {x}")
    
    def inner2():
        print(f"访问外层: {x}")
    
    def inner3():
        nonlocal x
        x = "修改后的outer变量"
        print(f"修改外层: {x}")
    
    inner()   # 输出: 最内层: inner变量
    inner2()  # 输出: 访问外层: outer变量
    inner3()  # 输出: 修改外层: 修改后的outer变量
    print(f"outer函数内: {x}")  # 输出: outer函数内: 修改后的outer变量

outer()
print(f"全局作用域: {x}")  # 输出: 全局作用域: 全局变量

解析

5. 闭包的实际应用

示例8:函数装饰器

def logger(func):
    def wrapper(*args, **kwargs):
        print(f"调用函数: {func.__name__}")
        result = func(*args, **kwargs)
        print(f"函数返回: {result}")
        return result
    return wrapper

@logger
def add(a, b):
    return a + b

print(add(3, 5))
# 输出:
# 调用函数: add
# 函数返回: 8
# 8

解析

示例9:配置特定函数

def make_adder(n):
    def adder(x):
        return x + n
    return adder

add5 = make_adder(5)
add10 = make_adder(10)

print(add5(3))   # 输出: 8
print(add10(3))  # 输出: 13

解析

6. 闭包与变量生命周期

示例10:闭包延长变量生命周期

def create_timer():
    start_time = time.time()
    
    def elapsed():
        return time.time() - start_time
    
    return elapsed

timer = create_timer()
time.sleep(1)
print(f"经过时间: {timer():.2f}秒")  # 输出: 经过时间: 1.00秒

解析

闭包使用注意事项

  1. 内存管理

    • 闭包会延长外部变量的生命周期
    • 可能导致内存泄漏(循环引用时)
    • 不再需要的闭包应及时解除引用
  2. 变量捕获

    • 闭包捕获的是变量本身,而非值
    • 循环中创建闭包需注意变量绑定
    functions = []
    for i in range(3):
        def func():
            return i
        functions.append(func)
    
    # 所有函数都返回2,因为捕获的是同一个i
    print([f() for f in functions])  # 输出: [2, 2, 2]
    
    # 正确做法:使用默认参数创建新绑定
    functions = []
    for i in range(3):
        def func(j=i):
            return j
        functions.append(func)
    
    print([f() for f in functions])  # 输出: [0, 1, 2]
    
  3. 性能考虑

    • 闭包访问比局部变量稍慢
    • 在性能关键代码中避免过度使用
    • 复杂状态管理考虑使用类
  4. 可读性

    • 避免过深的嵌套
    • 复杂的闭包逻辑应重构为类
    • 使用有意义的变量名

总结

函数内部访问外部作用域变量是Python的重要特性,它:

闭包是Python函数式编程的核心概念之一,合理使用可以:

理解作用域和闭包机制对于编写高质量的Python代码至关重要,它们是构建复杂应用的基础。

到此这篇关于Python函数作用域与闭包的文章就介绍到这了,更多相关Python函数作用域与闭包内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文