如何在全局作用域清空Python装饰器内部的列表a?
问题描述
原代码:
def outer(func): a = [] def inner(): func() a.append('work') print(a) return inner @outer def test(): print('TEST') test() test() # *1 test() # *2
需求:
- *1处想要清空装饰器内部的列表
a - *2处调用
test()时,outer内部必须是新的列表a - 能否在全局作用域实现?正确的实现方式是什么?
解决方案
默认情况下,装饰器outer仅在装饰test函数时执行一次,列表a是outer的局部变量,被闭包inner引用,无法直接在全局作用域访问。要实现需求,需要给闭包暴露操作a的接口:
修改后的代码:
def outer(func): a = [] def inner(): func() a.append('work') print(a) # 新增重置列表的方法,替换为新的空列表 def reset_a(): nonlocal a a = [] # 将方法绑定到inner函数对象上 inner.reset_a = reset_a return inner @outer def test(): print('TEST') test() test() # *1 此处调用重置方法,生成新的空列表a test.reset_a() test() # *2 此时使用的是新的空列表
运行结果:
TEST ['work'] TEST ['work', 'work'] TEST ['work']
说明
- 通过给闭包
inner添加reset_a方法,利用nonlocal关键字修改outer作用域内的a,将其替换为新的空列表,满足“outer内部必须是新的列表a”的需求。 - 如果仅需要清空原列表而非替换新列表,可以把
a = []改成a.clear()。 - 无法直接在全局作用域访问或修改
a,必须通过闭包提供的接口操作,因为a属于outer的局部作用域,不在全局命名空间中。
内容的提问来源于stack exchange,提问作者Yurii
相关产品推荐
相关产品推荐

