Python 装饰器中的命名关键字?

Python 装饰器中的命名关键字?,python,decorator,keyword,named-parameters,Python,Decorator,Keyword,Named Parameters,我一直在深入研究如何在查看其他人的代码之前编写自己版本的备忘录装饰器。老实说,这更像是一种有趣的锻炼。然而,在玩的过程中,我发现我不能对装饰师做我想做的事情 def addValue( func, val ): def add( x ): return func( x ) + val return add @addValue( val=4 ) def computeSomething( x ): #function gets defined 如果我想这

我一直在深入研究如何在查看其他人的代码之前编写自己版本的备忘录装饰器。老实说,这更像是一种有趣的锻炼。然而,在玩的过程中,我发现我不能对装饰师做我想做的事情

def addValue( func, val ):
    def add( x ):
        return func( x ) + val
    return add

@addValue( val=4 )
def computeSomething( x ):
    #function gets defined
如果我想这样做,我必须这样做:

def addTwo( func ):
    return addValue( func, 2 )

@addTwo
def computeSomething( x ):
    #function gets defined

为什么我不能以这种方式在decorator中使用关键字参数?我做错了什么?您能告诉我应该怎么做吗?

您需要定义一个返回装饰器的函数:

def addValue(val):
    def decorator(func):
        def add(x):
            return func(x) + val
        return add
    return decorator
def double():
  def middling():
    def inner(f):
      return f
    return inner
  return middling
当您编写@addTwo时,addTwo的值直接用作修饰符。但是,当您编写@addValue4时,第一个addValue4将通过调用addValue函数进行计算。然后将结果用作修饰符。

您希望部分应用函数addValue-提供val参数,但不提供func。通常有两种方法可以做到这一点:

第一个参数称为currying,用于interjay的回答:不是一个有两个参数fa,b->res的函数,而是编写一个第一个参数的函数,返回另一个接受第二个参数ga->hb->res的函数

另一种方法是functools.partial对象。它使用对函数的检查来确定函数在您的案例中运行func和val需要哪些参数。您可以在创建分部时添加额外参数,一旦调用分部,它将使用给定的所有额外参数

from functools import partial
@partial(addValue, val=2 ) # you can call this addTwo
def computeSomething( x ): 
    return x
对于这个部分应用程序问题,部分通常是一个简单得多的解决方案,特别是对于多个参数。

具有任何类型参数的装饰器-命名/关键字参数、未命名/位置参数或其中一些参数-本质上,你在@name行中调用的那些,而不是仅仅在那里提到的那些,需要两层嵌套,而你刚才提到的装饰器只有一层嵌套。如果您想在@line中调用它们,甚至对于无参数的函数也是如此-下面是最简单的、不做任何事情的双嵌套decorator:

def addValue(val):
    def decorator(func):
        def add(x):
            return func(x) + val
        return add
    return decorator
def double():
  def middling():
    def inner(f):
      return f
    return inner
  return middling
你会把这个当作

@double()
def whatever ...
请注意,在本例中,括号是空的,因为不需要也不需要参数:它们表示您正在调用double,它返回middling,修饰任何内容

一旦您了解了调用和仅提及之间的区别,添加例如可选的命名参数并不难:

def doublet(foo=23):
  def middling():
    def inner(f):
      return f
    return inner
  return middling
可用作:

@doublet()
def whatever ...
或作为:

@doublet(foo=45)
def whatever ...
或相当于:

@doublet(45)
def whatever ...

你是说在Python中,修饰符使用了热切的求值?真是个倒霉蛋。functools。偏,非常好。我知道有一种简单的方法可以在不需要三重缩进的情况下用Python完成咖喱。多谢。