Home > Back-end >  Clear list inside decorator from global scope
Clear list inside decorator from global scope

Time:01-30

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

Is it posible to clear list a, in global scope? If yes, how do it correct.

CodePudding user response:

It is possible if you define the decorator as a class:

(tested using 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']

CodePudding user response:

a does not exist at the global scope, rather as the cell_contents attribute of the first element of test.__closure__. 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.

CodePudding user response:

You can add a parameter to the wrapper function specifying whether to clear a before/after the original function executes.

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']
  • Related