Python Decorator 3.0和d的参数

2024-05-19 02:50:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我很高兴看到decoratorpython模块(3.0)的最新版本。它看起来比以前的迭代要干净得多(例如,语法比以往任何时候都更甜)。在

然而,对于那些自己接受参数的装饰者来说,它似乎有着糟糕的支持(例如,“sour”语法,可怕地延伸隐喻)。有没有人有一个很好的例子来说明如何使用decorator3.0干净利落地做到这一点?在

 def substitute_args(fun, arg_sub_dict):
      def wrapper(arg):
         new_arg = arg_sub_dict.get(arg, arg)
         return fun(new_arg)

      # some magic happens here to make sure that type signature, 
      # __name__, __doc__, etc. of wrapper matches fun

 return wrapper

Tags: 模块版本new参数returndef语法arg
2条回答

这是我刚刚发现的另一种方法:检查decorator的第一个(也是唯一一个)参数是否可调用;如果是,那么就完成了,并可以返回行为修改包装器方法(它本身用functools.wraps修饰以保留名称和文档字符串)。在

在另一种情况下,应该存在一个或多个命名参数或位置参数;您可以收集这些参数并返回一个callable,它接受一个callable作为第一个参数,并返回一个包装器方法,因为这个描述符合decorator方法的描述,所以返回这个装饰器方法!我在这里使用了functools.partial来获得我的decorator的一个版本,is_global_method(我现在正在研究它的实现当然是无稽之谈,如下所示,这只是为了演示装饰工作)。在

这个解决方案似乎有效,但确实需要更多的测试。如果你把我们的眼睛放大,你会发现窍门只有三四条线可以记住。现在我想知道是否可以将这种功能打包到另一个装饰器中?啊,真是太神奇了!在

from functools import wraps
from functools import partial

_               = print
is_instance_of  = isinstance
is_callable     = lambda x: hasattr( x, '__call__' )

def is_global_method( x, *, name = None ):
  if is_callable( x ):
    @wraps( x )
    def wrapper( *P, **Q ):
      return { 'name': name, 'result': x( *P, **Q ), }
    return wrapper
  # assert is_instance_of( x, str ) # could do some sanity checks here
  return partial( is_global_method, name = x )

@is_global_method
def f( x ):
  """This is method f."""
  return x ** 2

@is_global_method( 'foobar' )
def g( x ):
  """This is method g."""
  return x ** 2

_( f.__name__ )
_( f.__doc__ )
_( f( 42 ) )
_( g.__name__ )
_( g.__doc__ )
_( g( 42 ) )

在这种情况下,需要使函数返回decorator。(任何事情都可以通过另一个层次的间接寻址来解决…)

from decorator import decorator
def substitute_args(arg_sub_dict):
  @decorator
  def wrapper(fun, arg):
    new_arg = arg_sub_dict.get(arg, arg)
    return fun(new_arg)
  return wrapper

这意味着substitute_args本身不是一个装饰器,而是一个装饰器工厂。这是没有decorator模块的等价物。在

^{pr2}$

三个层次的深度不是很方便,但记住其中两个层次是在定义函数时:

@substitute_args({}) # this function is called and return value is the decorator
def f(x):
  return x
# that (anonymous) decorator is applied to f

相当于:

def f(x):
  return x
f = substitude_args({})(f) # notice the double call

相关问题 更多 >

    热门问题