繁体   English   中英

从全局 scope 清除装饰器内部列表

[英]Clear list inside decorator from global scope

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 所以这里必须是一个新的列表 a inside outer

是否可以清除全局 scope 中的列表 a? 如果是,如何纠正。

如果您将装饰器定义为 class,则有可能:

(使用 Python 3.11 测试)

class Outer:
    def __init__(self):
        self.a = []
    
    def reset(self):
        self.a = []
    
    def __call__(self, fn):
        def inner():
            fn()
            self.a.append('work')
            print(self.a)
        return inner

outer = Outer()

@outer
def test():
    print('TEST')


test()
# TEST
# ['work']
test()
# TEST
# ['work', 'work']

print(f'before-reset {outer.a}')
# before-reset ['work', 'work']

outer.reset()

print(f'after-reset {outer.a}')
# after-reset []

test()
# TEST
# ['work']

print(f'after-next test() {outer.a}')
# after-next test() ['work']

a在全局 scope 中不存在,而是作为test.__closure__的第一个元素的cell_contents属性存在。 可以将其重置为空列表,但我不建议像这样修改闭包。

>>> test()
TEST
['work']
>>> test()
TEST
['work', 'work']
>>> test.__closure__[0].cell_contents = []
>>> test()
TEST
['work']

您可能应该使用list值实例属性而不是使用闭包来定义 class。

您可以向包装器 function 添加一个参数,指定是否在原始 function a之前/之后清除。

def outer(func):
    a = []

    def inner(clear=False):
        func()
        a.clear() if clear else a.append('work')
        print(a)
    return inner

@outer
def test():
    print('TEST')

test()
test(clear=True)
# *1
test() # *2

结果:

TEST
['work']
TEST
[]
TEST
['work']

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM