如何检测函数是否已在本地定义?

2024-04-19 19:27:18 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中,我有一个decorator,如果函数是在调用它的函数中本地定义的,它必须跳过任何实际工作。我做了一个简单的测试脚本:

def fn1():
    # @my_decorator will be here
    def fn2():
        pass

    print(fn2)
    return fn2

x = fn1()
print(x)
print(x.__module__)

它打印的是:

^{pr2}$

如我所见,Python看到函数是在局部空间中定义的(在打印文本中是<locals>),但我不知道如何找到这部分数据。我浏览了inspect模块,没有看到类似的内容。在

我不能依赖函数是否是全局函数。在

我用什么?在


Tags: 函数脚本returnhere定义mydefdecorator
2条回答

首先,直接方法是检查the ^{} flag is set on the function's code object

import inspect

...

def is_nested(func):
    return func.__code__.co_flags & inspect.CO_NESTED

def deco(func):
    if is_nested(func):
        # This is a nested function, return it unchanged
        return func
    ... otherwise, do your decoration here ...

也就是说,如果你关心的是你是否真的结束了任何事情,还有另一种方法。一个不使用封闭范围中任何内容的函数是嵌套的,但不是闭包,这种区别通常很重要。例如:

^{pr2}$

因为bar没有使用foo调用范围内的变量,所以不是正在进行闭包。相比之下,即使它是一个垃圾引用,这个只是通过从封闭范围中读取x的值来实现闭包:

^{3}$

可以通过测试__closure__属性(如果没有嵌套变量被关闭,则为None)或检查__code__对象的co_freevars属性(这是一个封闭的名称元组,因此如果它是空的,那么它就不是闭包,尽管它可能仍然是一个嵌套函数):

def is_closure(func):
    return func.__closure__ is not None
    # Or using documented names, since __closure__ isn't for some reason,
    # co_freevars is a tuple of names captured from nested scope
    return bool(func.__code__.co_freevars)

    # Or on 3.3+, you even get a function to aid you:
    return bool(inspect.getclosurevars(func).nonlocals)

好吧,这里有个老套的方法:

'<locals>' in f.__qualname__

不过,我觉得它很脆弱。在

另一种方法是使用Frame,但我更不喜欢这样,我想:

^{pr2}$

相关问题 更多 >