[英]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.