如果从另一个脚本导入一个经过修饰的python函数,会发生什么?

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

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

我正在查看一个flask后端中带有装饰器的函数,并考虑将其导入另一个脚本并以不同的方式装饰它。有人知道当你导入它时会发生什么吗,不管装饰师是否同意?你知道吗

我看过this,但它更多地讨论了在同一个脚本中发生的事情。你知道吗


Tags: 函数脚本flask方式装饰this事情时会
2条回答

不,导入修饰函数不会删除修饰器。你知道吗

导入从源模块的全局命名空间中检索当前对象,修饰函数会导致decorator返回值存储在全局命名空间中。你知道吗

对于modulename = sys.modules['modulename'](对于import modulename)和objectname = sys.modules['modulename'].objectname赋值(对于from modulename import objectname,在任何一种情况下,首先确保sys.modules加载了所需的模块之后),导入模块都是语法上的糖分,模块中的全局变量与模块对象上的属性是一样的。装饰只是functionname = decorator(functionobject)的语法糖。你知道吗

如果需要向导入的函数添加新的decorator,只需调用decorator:

from somemodule import somedecoratedfunction

newname_or_originalname = decorator(somedecoratedfunction)

如果导入的修饰函数不适合在新层中再次修饰,或者您希望访问原始的未修饰函数,请查看对象是否具有__wrapped__属性:

from somemodule import somedecoratedfunction

unwrapped_function = somedecoratedfunction.__wrapped__

编写良好的decorators使用^{} decorator,它将该属性设置为指向原始属性:

>>> from functools import wraps
>>> def demodecorator(f):
...     @wraps(f)
...     def wrapper(*args, **kwargs):
...         print("Decorated!")
...         return f(*args, **kwargs)
...     return wrapper
...
>>> @demodecorator
... def foo(name):
...     print(f"Hello, {name or 'World'}!")
...
>>> foo('cardamom')
Decorated!
Hello, cardamom!
>>> foo.__wrapped__('cardamom')
Hello, cardamom!

修饰函数

@some_decorator
def some_func(...):
    ...

相当于将函数应用于另一个对象:

def some_func(...):
    ...

some_func = some_decorator(some_func)

导入模块时,您可以访问的只是当前绑定到some_func的对象,它是应用于原始函数的some_decorator的返回值。除非返回的东西some_decorator包含对原始未修饰函数的引用,否则您无法从导入的模块访问它。你知道吗

原作曝光示例:

def some_decorator(f):
    def _(*args, *kwargs):
        # Do some extra stuff, then call the original function
        # ...
        return f(*args, **kwargs)
    _.original = f
    return _

@some_decorator
def some_func(...):
    ...

导入模块时,some_module.some_func引用修饰函数,但原始的未修饰函数可通过some_module.some_func.original使用,但仅可用,因为编写修饰器是为了使其可用。(正如Martijn Peters指出的,wraps装饰器为您做了这件事和其他一些好事,但是装饰器仍然需要使用wraps。)

相关问题 更多 >