简体   繁体   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 here I want clear list a inside a decorator *2 so here must be a new list a inside outer *1 这里我想要一个装饰器里面的清晰列表 a *2 所以这里必须是一个新的列表 a inside outer

Is it posible to clear list a, in global scope?是否可以清除全局 scope 中的列表 a? If yes, how do it correct.如果是,如何纠正。

It is possible if you define the decorator as a class:如果您将装饰器定义为 class,则有可能:

(tested using Python 3.11) (使用 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 does not exist at the global scope, rather as the cell_contents attribute of the first element of test.__closure__ . a在全局 scope 中不存在,而是作为test.__closure__的第一个元素的cell_contents属性存在。 You can reset it to an empty list, but I don't recommend modifying closures like this.可以将其重置为空列表,但我不建议像这样修改闭包。

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

You should probably instead define a class with a list -valued instance attribute instead of using a closure.您可能应该使用list值实例属性而不是使用闭包来定义 class。

You can add a parameter to the wrapper function specifying whether to clear a before/after the original function executes.您可以向包装器 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

Result:结果:

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

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

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