6

Here is my decorator code. I'm getting UnboundLocalError for some reason but I couldn't find it.

>>> def validate(schema=None):
        def wrap(f):
            def _f(*args, **kwargs):
                if not schema:
                schema = f.__name__
            print schema
            return f()
            return _f
        return wrap

>>> @validate()
    def some_function():
        print 'some function'


>>> some_function()
Traceback (most recent call last):
  File "<pyshell#27>", line 1, in <module>
    some_function()
  File "<pyshell#22>", line 4, in _f
    if not schema:
UnboundLocalError: local variable 'schema' referenced before assignment
>>> 

So, I thought maybe it's better to post here. I might be missing something.

Thanks.

pocoa
  • 4,197
  • 9
  • 37
  • 45

1 Answers1

11

The compiler can't determine schema's proper scope. Either use nonlocal schema (3.x) within _f() or change the definition of _f() slightly:

def _f(self, schema=schema, *args, **kwargs):
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Hi Ignacio. What do you mean by nonlocal schema? – pocoa Apr 12 '11 at 04:46
  • 1
    I mean the word `nonlocal`, followed by a space, followed by the word `schema`. http://www.python.org/dev/peps/pep-3104/ – Ignacio Vazquez-Abrams Apr 12 '11 at 04:47
  • Thanks Ignacio, it works! I'm not using 3.x. Is this the only way to make it work in 2.x? – pocoa Apr 12 '11 at 05:03
  • Yes. The compiler does not generate bytecode to look in outer scopes since you assign to it, so you must force it to be in the local scope instead. – Ignacio Vazquez-Abrams Apr 12 '11 at 05:06
  • I was looking for some similar implementations and I found this one: https://bitbucket.org/jpellerin/unittest2/src/3b0898db0e0f/unittest2/case.py This is very similar and it works. Please take a look at the skip decorator. – pocoa Apr 12 '11 at 06:09
  • 1
    That decorator never assigns to `reason`. – Ignacio Vazquez-Abrams Apr 12 '11 at 06:12
  • If I try using the suggested method for Python 2, this forces the wrapped function to pass the "schema" argument - or it uses the wrapped function arguments to assign to "schema", so this doesn't really work for wrapping function with arguments – Evgen Apr 07 '17 at 23:58