装饰器能在运行时与lambda表达式一起工作吗?

16 投票
2 回答
20777 浏览
提问于 2025-04-16 12:24
def attrs(**kwds):
      def decorate(f):
          for k in kwds:
              setattr(f, k, kwds[k])
          return f
      return decorate

@attrs(argument_types=(int, int,), returns=int)
def add(a, b):
      return a + b 

在这里,我需要add()函数能够显示它可以接受的参数类型。可是,我能在运行时做到这一点吗?

ladd=[]
for x in range(0,10):

      @attrs(argument_types=int, returns=int,default_parameter1 = x) 
      exp =  lambda : add(a,x)  
      ladd.append(exp)

或者

ladd=[]
for x in range(0,10):

      @attrs(argument_types=int, returns=int,default_parameter1 = x) 
      addx = functools.partial(add, 2)  
      ladd.append(addx)

我需要这些函数能够在运行时生成,并且可以绑定“装饰器”参数。


好吧,这里是错误信息,我觉得上面的代码可能无法工作,但我从来没有试过把它粘贴到python里测试一下……

>>> ladd=[]
>>> for x in range(0,10):
...     @attrs(argument_types=int, returns=int,default_parameter1 = x) 
...     exp =  lambda : add(a,x)  
  File "<stdin>", line 3
    exp =  lambda : add(a,x)  
      ^
SyntaxError: invalid syntax
>>>     ladd.append(exp)
  File "<stdin>", line 1
    ladd.append(exp)
    ^
IndentationError: unexpected indent
>>> 

2 个回答

13

这个@的写法其实是为了让我们更方便地使用装饰器,它的作用就是把下一个函数作为参数传给装饰器。也就是说,

@deco
def func(): pass

和下面的写法是一样的:

def func(): pass
func = deco(func)

所以你想要的其实就是:

ladd=[]

for x in range(0,10):    
      deco = attrs(argument_types=int, returns=int,default_parameter1 = x) 
      addx = functools.partial(add, 2)
      # append the "decorated" function
      ladd.append(deco(addx))
19

装饰器的语法其实就是一种语法上的简化,虽然它能引导人们思考一些有趣的方向。

@expr
def f(...):
    ...

这和下面的内容是一样的

def f(...):
    ...
f = expr(f)

所以你可以直接使用 attrs(argument_types=..., ...)(lambda: ...)

撰写回答