First of all, a direct approach is to check if the CO_NESTED flag is CO_NESTED on the function code object :
import inspect ... def is_nested(func): return func.__code__.co_flags & inspect.CO_NESTED def deco(func): if is_nested(func):
However, there is another approach if you care about whether you really closed something. A function that does not use anything from the enclosing area is nested but not closing, and this distinction is often important. For example:
def foo(x): def bar(y): pass return bar
does not make a closure because bar does not use any variables from the scope of the foo call. In contrast, although this is a reference to garbage, it does close simply by reading the x value from the enclosing area:
def foo(x): def baz(y): pass return bar
You can determine the difference between bar and baz by testing the __closure__ attribute (which is None if the nested variables have not been closed) or by checking the co_freevars __code__ object attribute (which is a tuple of names closed, so if it is empty, then this is either not a closure , although it can still be a nested function):
def is_closure(func): return func.__closure__ is not None
Shadowranger
source share