【问题标题】:python: decorate function with default kwargspython:用默认kwargs装饰函数
【发布时间】:2013-07-05 16:20:22
【问题描述】:

如何定义一个装饰器decor 来完成这项工作?有很多关于这个的帖子,但我仍然没有找到解决方案。也许这是一个非常糟糕的主意。

示例1,编写一个函数,直到应用装饰器才被破坏:

defaults = {'a': 1, 'b': 2}

@decor(defaults)
def f(x):
    print(x, a, b)

示例 2:

defaults = {'a': 1, 'b': 2}

@decor(defaults)
def fun(x):
   print(locals())

f(3)

应该给

{'b': 2, 'x': 3, 'a': 1}

或者更清楚一点,我希望装饰器修改签名,以便 help(f) 给出

Help on function f in module __main__:

f(x, a=1, b=2)

【问题讨论】:

  • 不要!动态修改 local 变量确实是错误的,而且实际上很难可靠地实现而不在程序中引入严重的安全风险。如果您提供一些上下文,您可能会发现有 3-4 种更好的方法可以实现您想要的,而无需这样做。
  • 如果不重写 f 字节码,您就无法做到这一点。你真的不想去那里。你真正想解决什么问题?
  • 不是重复的,但这可能会有所帮助:stackoverflow.com/questions/5929107/…
  • 从根本上说,您将如何使用它?您的装饰函数必须引用“默认”变量才能使用它们。鉴于此,使用此装饰器将使您的代码更加更难阅读。不要这样做。
  • @mathtick 这将使维护变得更加困难。

标签: python decorator


【解决方案1】:

好的,你已经被警告过这是不安全的,但只是为了好玩,这个装饰器必须工作,无论装饰函数是否接收 kwargs

import inspect as insp

def modify(f, defaults):
    lines = insp.getsourcelines(f)[0]
    lines.pop(0) # remove decorator heading
    for k, v in defaults.items():
        lines.insert(1, '    %s = %s\n' % (k, v))
    exec ''.join(lines)
    return locals()[f.__name__]

def decor(defaults):
    def wrap(f):
        def wrapped_f(*args):
            new_f = modify(f, defaults)
            return new_f(*args)
        return wrapped_f
    return wrap

【讨论】:

  • 哈哈,这看起来很危险。我正在细化这个问题。逐渐接近说服自己这是一个非常糟糕的主意。
  • 好的,我更正了代码,现在它可以作为装饰器了 :) @Shaung,魔法很酷,但如果我没记错的话,它需要字节播放,它不在标准库中
【解决方案2】:

不确定这是否是你真正想要的,但这里是

defaults = {'a': 1, 'b': 2}

def decor(**kw_dec):
    def decorate(func):
        def ret(*args, **kwargs):
            func(*args, **dict(kw_dec, **kwargs))
        return ret
    return decorate


def fun(*args, **kwargs):
    print(locals())

fun = decor(**defaults)(fun)
fun(3)

给予

{'args': (3,), 'kwargs': {'a': 1, 'b': 2}}

【讨论】:

  • 理想情况下,“装饰”应该适用于任何功能。拥有 kwargs 需要乐趣,据我所知,签名并没有真正保留。
猜你喜欢
  • 2016-04-22
  • 2016-09-27
  • 1970-01-01
  • 2018-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-09
相关资源
最近更新 更多