I want to do this (dummy example):
def func():
nonlocal var
print (var)
class A:
var = 'hola'
func()
But I get: "SyntaxError: no binding for nonlocal 'var' found"
What I really intend to do is append a method name to a list in the scope of the class if that method is decorated. Something like this:
def decorator(func):
nonlocal decorated
decorated.append(func.__name__)
return func
class A:
decorated = []
@decorate
def f(self):
pass
Python just doesn't let you do this. You can access the class namespace by using locals()
. But at this point, you might as well just pass the variable you're interested in to the decorator.
# using locals()
def decorator(class_namespace):
def _decorator(func):
class_namespace["decorated"].append(func)
return func
return _decorator
class A:
store = decorator(locals())
decorated = []
@store
def func(self):
pass
del store
Generally, it's easy to use a pair of decorators. One to mark the functions you're interested in, and one to collect them.
from types import FunctionType
def collect(cls):
for item in vars(cls).values():
print(item)
if isinstance(item, FunctionType) and getattr(item, "marked", False):
cls.marked_funcs.append(item)
return cls
def mark(func):
func.marked = True
return func
@collect
class B:
marked_funcs = []
@mark
def func(self):
pass
But in your case it might just be simpler to create the set of function names at the end of the class. eg.
class C:
def func(self):
pass
func_names = [f.__name__ for f in [func]]