我有一个以下的小型Python程序:
def wrap(func):
print "before execution ..."
a = func()
print "after execution ..."
return a
@wrap
def dosomething():
print "doing something ..."
当我执行上面的脚本时,我不应该得到任何输出,因为我没有打电话:
DoSomething的()
但是当我执行这个脚本时,我得到以下输出:
before execution ...
doing something ...
after execution ...
请解释此行为的原因
答案 0 :(得分:3)
当您使用@
时,您正在装饰您正在使用其他功能进行注释的功能。使用装饰器语法时会调用装饰器外部函数 - 这是有道理的。
如果你想制作一个真正的装饰器,你需要将dosomething()
调用包装在装饰器体中的另一个函数中并返回这个新函数 - 就像那样:
def wrap(func):
print "before execution ..."
def inner():
a = func()
return a
print "after execution ..."
return innner
@wrap
def dosomething():
print "doing something ..."
答案 1 :(得分:2)
装饰器只是一个可调用函数,它将函数作为参数并返回替换函数。我们将简单地开始,逐步向有用的装饰者发展。
@符号将装饰器应用于函数,因此它等于:
dosomething = wrap(dosomething)
哪个运行换行。并打印输出。
这里有一些关于装饰器的信息: https://wiki.python.org/moin/PythonDecorators
http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/
答案 2 :(得分:1)
这是装饰者。阅读它here。
你到底在做什么: -
def wrap(func):
print "before execution ..."
a = func()
print "after execution ..."
return a
def dosomething(): # if you remove this decorator symbol
print "doing something ..."
wrap = wrap(dosomething) # this is what that `@wrap` is doing.
wrap()
这是两个步骤: -
1: - @wrap
将dosomething
函数的对象传递给wrap
函数。
wrap = wrap(dosomething) # passing `dosomething` object to `wrap`
2: - 现在调用wrap函数
wrap()
答案 3 :(得分:1)
执行装饰器代替函数定义。导入模块(或运行它)后,将执行所有顶级语句(类,函数等)。如果你在另一个函数中有你的装饰函数,它内部的装饰器只会在输入函数时执行,如下所示:
def main():
@wrap
def dosomething():
print "doing something ..."
简而言之......你不应该在装饰者中调用你的函数,而是返回一个包装函数,它会做你想要的。
您希望通过以下方式定义装饰器以实现"预期"结果:
def wrap(func):
def wrapped(*args, **kwargs):
print "before execution ..."
func(*args, **kwargs)
print "after execution ..."
return wrapped
答案 4 :(得分:1)
Python解释器执行它正在阅读的源文件中的所有代码。
然而,执行def
块并不执行包含的代码,它只是创建一个函数对象,这就是为什么你想知道为什么def
代码仍在运行。
这里有一个装饰器,翻译成:
dosomething = wrap(dosomething)
dosomething()
运行这些功能。