简体   繁体   中英

Python's is losing scope when I use a classmethod as a decorator wrapper

when I:

  1. Use a classmethod as a decorator wrapper

  2. Have a conditional statement inside the decorator

  3. Put a variable assignment inside the decorator

python raises an UnboundLocalError exception.

However, when I remove the variable assignment and replace it with a print function everything works fine (it does print). Which indicate that the variable is indeed defined.

Snippet 1

class TestClass:
    @classmethod
    def include(cls, name=None):
        def dec(func):
            if name is None:
                name=1
            return func
        return dec
@TestClass.include()
def test(): pass

Snippet 2

class TestClass:
    @classmethod
    def include(cls, name=None):
        def dec(func):
            if name is None:
                print(name)
            return func
        return dec
@TestClass.include()
def test(): pass

In snippet 1 nothing should happen but it raised the following exception:

Traceback (most recent call last):
  File "main.py", line 9, in <module>
    @TestClass.include()
  File "main.py", line 5, in dec
    if name is None:
UnboundLocalError: local variable 'name' referenced before assignment

Snippet 2 prints None as it should.

Am I doing something wrong? or is this a problem in python's implementation?

The decorator is a red herring. All that is happening here is that you are trying to assign to the nonlocal variable name from inside the function dec .

Whenever you assign to a variable inside a function in Python that variable is automatically local to the function unless you explicitly tell Python that it should be treated as nonlocal or global .

Just add a nonlocal declaration and it will do what you expected:

class TestClass:
    @classmethod
    def include(cls, name=None):
        def dec(func):
            nonlocal name 
            if name is None:
                name=1
            return func
        return dec
@TestClass.include()
def test(): pass

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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