3

im trying to access my decorators arguments inside the wrapper function with no luck.

what i have is:

def my_decorator(arg1=False, arg2=None):

    def decorator(method):
        @functools.wraps(method)
        def wrapper(method, *args, **kwargs):
            # do something based on arg1 and arg2
            # accessing one of the two named arguments
            # ends up in a 'referenced before assignment'

            arg1 = arg1 # error
            arg2 = arg2 # error

            newarg1 = arg1 # working
            newarg2 = arg2 # working

            return method(*args, **kwargs)
        return wrapper
    return decorator

and i would use it like a normal decorator

@my_decorator(arg1=True, arg2='a sting or whatever else')
the_function()

i really don't understand why i can't access the decorators arguments.

Lesmana
  • 25,663
  • 9
  • 82
  • 87
aschmid00
  • 7,038
  • 2
  • 47
  • 66

2 Answers2

4

You can access arg1 and arg2, but you should not assign to these names, not even with "augmented" assign operators, because this would make them local variables in the inner function. The error message you get shows that you tried to do exactly this (though you did not show your code).

In Python 3, you can work around this problem using

nonlocal arg1, arg2

somewhere in wrapper().

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
0

It depends on what you do with arg1 and arg2. Generally, closures work perfectly without extra work. However, if you re-assign them in the inner function, Python assumes it's a local variable and you have to tell it otherwise.

In Python 3, declare nonlocal arg1, arg2. In Python 2, you have to cheat: Wrap the two into lists (arg1 = [arg1] in the outer function) and use arg1[0] in the inner function. If you want an explanation of why this works, either search for Python questions on this topic or refer to the documentation (somewhere in the language reference I believe, I'll search).

Your problem is that wrapper passes self to method. There's no self. You'd have to take it (and even then, you'd restrict the decorator to methods - why not let self slip into *args?).

I fail to see how you read "referenced before assignment" from "global name self is not defined"...

Zulu
  • 8,765
  • 9
  • 49
  • 56
  • i dont reassign those args and i use python2x but i cant access those. it tells me that they are not assigned. – aschmid00 Feb 10 '11 at 21:42
  • @delnan: there is any code more to show. arg1 or arg2 are not accessible inside the wrapper function. i dont need to reassign those, only know if those are true or false or whats the value for arg2 – aschmid00 Feb 10 '11 at 21:48
  • @aschmid00: What is the code of `wrapper`? I doubt it's just three comments and a `return`, because that doesn't cause errors. –  Feb 10 '11 at 21:50
  • @delnan: try to use that decorator on a function and print the arguments. i cant even print those. because the wrapper func does not know about those arguments. – aschmid00 Feb 10 '11 at 21:52
  • @aschmid00: There is an error, but it has nothing to do with that vague retelling of an error message you gave us. See updated answer. (Edit: Now I see you've updates the code yourself... the version without `self` works flawlessly for me, if you still have issues, **post the code**). –  Feb 10 '11 at 22:00
  • @delnan: im making some progress. its not the self. i use self because the decorator needs to access the classes functions. it actually has something to do with an assignment of the args value to a nother local arg named the same. you were right... it was the code inside the wrapper function. ill update the post as soon as i understood what the acutal issue was. thank you for your help. – aschmid00 Feb 10 '11 at 22:13
  • @aschmid00: Why not post the whole code so we can help finding the issue? –  Feb 10 '11 at 22:16
  • i didnt post it the first time because i didnt realize that the issue was further in the code. ill post the whole code next time. i edited the post and added the solution. – aschmid00 Feb 10 '11 at 22:25