<p>原因是在考虑了decorator如何转换函数以及函数本身就是Python中的对象之后。在</p>
<p>我们从后者开始。在</p>
<h2><strong><em>函数是对象:</em></strong></h2>
<p>当我们考虑函数名后两对括号的含义时,这是立即的。考虑这个简单的例子(Python3):</p>
<pre><code>def func(x):
def func2(y):
return x + y + 1
return func2
result = func(5)(10)
print(result) # 15
</code></pre>
<p>这里“func”返回一个函数对象“func2”,因此您可以使用:</p>
^{pr2}$
<p>您可以将此视为先调用</p>
<pre><code>func(5)
</code></pre>
<p>并将“(10)”应用于结果对象,即函数!所以你有:</p>
<pre><code>func2(10)
</code></pre>
<p>现在既然定义了“x”和“y”,那么“func2”可以将最终值返回到“result”。在</p>
<p>记住,这是可能的,因为函数本身就是对象,而且“func”返回的是函数对象</p>
<pre><code>func2
</code></pre>
<p>并且<strong>不是</strong>它的结果(它不是单独调用函数)</p>
<pre><code>func2()
</code></pre>
<p>简言之,这意味着对于包装函数,第二组参数用于内部函数(如果包装器返回内部函数对象)。在</p>
<h2><strong><em>装饰者:</em></strong></h2>
<p>在您的示例中,“main”在最后一行中调用“fun1”</p>
<pre><code>return fun1(decarg)
</code></pre>
<p>因为装修工</p>
<pre><code>@dec(decarg)
</code></pre>
<p>实际上,你可以把“fun1”想象成:</p>
<pre><code>fun1 = dec(decarg)(fun1)
</code></pre>
<p>因此,“main”中的最后一行相当于:</p>
<pre><code>return dec(decarg)(fun1)(decarg)
</code></pre>
<p>根据前面的解释,找到问题应该很简单!在</p>
<ul>
<li><code>dec(decarg)</code>被执行并返回一个“_dec”函数对象;注意这个“decarg”是在第一个括号中传递的对象,因此在decorator中也是这样。在</li>
<li><code>_dec(fun1)</code>执行并返回一个“\u fun”函数对象。在</li>
<li><code>_fun(decarg)</code>执行并使用return语句调用fun1(decargs),这将在fun1(3)中正确转换,这是您得到的结果;请注意,这个“decarg”是在第三个括号中传递的,因此当您在main中调用“fun1”时也是如此。在</li>
</ul>
<p>你不能得到13,因为你没有调用“fun1”的结果</p>
<pre><code>funarg = decarg + 7
</code></pre>
<p>作为参数,而是使用从main传递给“\u fun”的“degarg”作为位置参数(funarg=decarg)来调用它。在</p>
<p>不管怎样,我必须感谢您提出这个问题,因为我正在寻找一种简单的方法,只在调用函数时才将参数传递给decorator,这非常有效。在</p>
<p>下面是另一个可能有帮助的示例:</p>
<pre><code>from functools import wraps
def add(addend):
def decorator(func):
@wraps(func)
def wrapper(p1, p2=101):
for v in func(p1, p2):
yield v + addend
return wrapper
return decorator
def mul(multiplier):
def decorator(func):
@wraps(func)
def wrapper(p1, p2=101):
for v in func(p1, p2):
yield v * multiplier
return wrapper
return decorator
def super_gen(p1, p2=101, a=0, m=1):
@add(a)
@mul(m)
def gen(p1, p2=101):
for x in range(p1, p2):
yield x
return gen(p1, p2)
</code></pre>