面试题答案
一键面试def call_counter(func):
count = 0
def wrapper(*args, **kwargs):
nonlocal count
count += 1
print(f"函数 {func.__name__} 被调用次数: {count}")
return func(*args, **kwargs)
return wrapper
@call_counter
def example_function():
print("执行示例函数")
# 调用示例函数
example_function()
example_function()
闭包工作原理
在上述代码中,call_counter
是外部函数,wrapper
是内部函数。当 call_counter
被调用时,它返回 wrapper
函数对象。此时,wrapper
函数虽然已经返回,但它记住了外部函数 call_counter
作用域中的 count
变量和 func
变量(func
是被装饰的函数)。即使 call_counter
的执行结束,count
变量仍然被 wrapper
函数引用,这就形成了闭包。通过 nonlocal
关键字,wrapper
函数可以修改外部函数作用域中的 count
变量。
装饰器工作原理
装饰器本质上是一个函数,它以另一个函数作为参数,并返回一个新的函数(通常是包装了原始函数的新函数)。在代码中,@call_counter
语法糖等价于 example_function = call_counter(example_function)
。这样,example_function
实际上指向了 call_counter
返回的 wrapper
函数。每次调用 example_function
时,实际执行的是 wrapper
函数。wrapper
函数在执行被装饰函数 func
之前,先增加 count
并打印调用次数,然后再调用 func
并返回其结果。