简体   繁体   English

使用修饰函数作为函数的默认参数

[英]Using a decorated function as a function's default argument

Consider this module:考虑这个模块:

#mymodule.py
import logging

def print_start_end(name):
    """
    Decorator that creates a logger and logs the start 
    and the end of the function call
    """
    def decorator(f):
        logger = logging.getLogger(name)
        def wrapper(*args, **kwargs):
            logger.info("start")
            res = f(*args, **kwargs)
            logger.info("end")
            return res
        return wrapper
    return decorator

@print_start_end(__name__)
def f(x):
    return x

def g(y=f(3)):
    return y

And an example script:和一个示例脚本:

import logging
from mymodule import f

logger = logging.getLogger("")
logger.setLevel(logging.INFO)
h = logging.StreamHandler()
h.setLevel(logging.INFO)
logger.addHandler(h)

print f(3)

Output:输出:

start
end
3

The decorator is working.装饰器正在工作。 But now I write a script to use g instead of f :但是现在我写了一个脚本来使用g而不是f

import logging
from mymodule import g

logger = logging.getLogger("")
logger.setLevel(logging.INFO)
h = logging.StreamHandler()
h.setLevel(logging.INFO)
logger.addHandler(h)

print g()

Output:输出:

3

When executing the statement print g() , the call to f was successful because it printed the expected return value 3. But why doesn't it also print "start" and "end"?在执行语句print g() ,对f的调用成功了,因为它打印了预期的返回值 3。但是为什么它不打印“start”和“end”呢?

The problem is that the default value is evaluated immediately, before the logger has been initialized.问题是在初始化记录器之前立即评估默认值。 The way around this is to defer execution until afterwards.解决这个问题的方法是将执行推迟到之后。

def g(y=lambda:f(3)):
    return y()

Note that the f(3) in def g(y=f(3)): is executed only once , when the function is defined, not every time when it is called.注意, f(3)def g(y=f(3)):只执行一次,当函数定义,而不是当它被称为每次。

Thus, the problem seems to be that by the time f(3) is executed in mymodule , the logger is not yet initialized.因此,问题似乎是在mymodule执行f(3) ,记录器尚未初始化。 Initialize first, then import, then it works:首先初始化,然后导入,然后它工作:

import logging

logger = logging.getLogger("")
logger.setLevel(logging.INFO)
h = logging.StreamHandler()
h.setLevel(logging.INFO)
logger.addHandler(h)

from mymodule import g

print g()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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