1

I have a case similar to this -

flag = True
print "Before All things happened, flag is", flag
def decorator(*a):
    def real_decorator(function):
        def wrapper(*args, **kwargs):
            global flag
            flag = False
            print "just in real decorator before function call i.e. before", function.__name__
            print "flag is " , flag
            function(*args, **kwargs)
            print "In real decorator after function call i.e. after", function.__name__
            flag = True
            print "flag is ", flag
        return wrapper
    return real_decorator

@decorator()
def subtota():
    print "in subtota"
    print "flag is" , flag

@decorator()
def print_args(*args):
    print "in print args"
    for arg in args:
        print arg
    print "flag is ", flag
    subtota()
    print "we do want flag to be false here, after subtota"
    print "but, flag is ", flag


print_args("bilbo", "baggins")

print "after All things happended flag is ", flag

And the output is

Before All things happened, flag is True
just in real decorator before function call i.e. before print_args
flag is  False
in print args
bilbo
baggins
flag is  False
just in real decorator before function call i.e. before subtota
flag is  False
in subtota
flag is False
In real decorator after function call i.e. after subtota
flag is  True
we do want flag to be false here, after subtota
but, flag is  True
In real decorator after function call i.e. after print_args
flag is  True
after All things happended flag is  True

Here, I do not want to change the value of flag after subtota() or may be we can say that, we want to keep behaviors of each function independent to each other. How can we achieve this? PS - Cannot avoid using Module-level global variable flag.

EDIT- desired behavior - Only after the uppermost function is executed, the flag should be false.

1
  • So what output where you hoping for instead? I've made a stab at answering, but adding a description of the expected behaviour would be helpful. Commented Jun 4, 2015 at 20:14

3 Answers 3

2

I find it a little unclear as to what your goal is here.

If you need to track per-function state, you can set a flag on the decorated function object itself:

def decorator(*a):
    def real_decorator(function):
        def wrapper(*args, **kwargs):
            function.flag = False
            function(*args, **kwargs)
            function.flag = True
        return wrapper
    return real_decorator

You could also set it on wrapper here to make the flag available on the decorated version:

wrapper.flag = False

If you need to toggle the flag only on entering and exiting the outermost decorated call, you could use a separate global to count how many levels in you are; you may as well set that on the decorator function:

def decorator(*a):
    decorator._depth = 0
    def real_decorator(function):
        def wrapper(*args, **kwargs):
            global flag
            if decorator._depth == 0:  # entering outermost call
                flag = False

            decorator._depth += 1
            function(*args, **kwargs)
            decorator._depth -= 1

            if decorator._depth == 0:  # exiting outermost call
                flag = True
        return wrapper
    return real_decorator
Sign up to request clarification or add additional context in comments.

4 Comments

Nice! But there is one catch! flag is a global var. If I try to use function.flag value outside the decorator in some other function(which in turn is accessing the flag var), I would not get the current value, right?
@malhar: set it on wrapper in that case. Now print_args.flag references that exact same value for the decorated print_args function, and subtota.flag is the other flag.
Martjin, This appears not to be working as my flag var is global and is used in another function. can I use wrapped.flag in some other function which is defined outside the decorator?
@malhar: added a stack tracking option; count how many layers in you are and only toggle the global when in the outermost call.
1

Save the old value of flag inside wrapper, and restore to it instead of True

Comments

0

Apart from using variable which is scoped to the decorator, I tried using the following method-

def decorator(*a):
def real_decorator(function):
    def wrapper(*args, **kwargs):
        global flag
        old_flag = flag
        flag = False
        function(*args, **kwargs)
        flag = old_flag
    return wrapper
return real_decorator

This seems a bit easy, and works perfectly fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.