【问题标题】:Adding a method to a function object at runtime在运行时向函数对象添加方法
【发布时间】:2010-04-17 21:11:31
【问题描述】:

我之前读过一个问题,询问 Python 中是否有 times 方法,该方法允许连续调用函数 n 次。

每个人都建议for _ in range(n): foo(),但我想尝试使用函数装饰器编写不同的解决方案。

这是我所拥有的:

def times(self, n, *args, **kwargs):
    for _ in range(n):
        self.__call__(*args, **kwargs)

import new
def repeatable(func):
    func.times = new.instancemethod(times, func, func.__class__)

@repeatable
def threeArgs(one, two, three):
    print one, two, three

threeArgs.times(7, "one", two="rawr", three="foo")

当我运行程序时,我得到以下异常:

回溯(最近一次通话最后): 文件“”,第 244 行,在 run_nodebug 文件“C:\py\repeatable.py”,第 24 行,在 threeArgs.times(7, "one", two="rawr", three="foo") AttributeError:“NoneType”对象没有属性“次”

所以我想装饰器没有工作?我该如何解决这个问题?

【问题讨论】:

  • 与您要替换的方法相比,这种方法似乎不那么惯用和简单。

标签: python function decorator


【解决方案1】:

你的装饰器应该返回函数对象:

def repeatable(func):
    func.times = new.instancemethod(times, func, func.__class__)
    return func

现在它什么也不返回了,所以你实际上在 None 中改变了 threeArgs

这是因为:

@decorator
def func(...):
    ...

大致相同:

def func(...):
    ....
func = decorator(func)

【讨论】:

  • 太棒了,我想我应该想到...哦,好吧,谢谢你的帮助
【解决方案2】:

您在 repeatable 装饰器的末尾缺少 return func 语句。

【讨论】:

    【解决方案3】:

    您是否考虑过不将其添加到特定函数中,而是允许将其与 any 函数一起使用?

    def times(n, func, *args, **kwds):
      return [func(*args, **kwds) for _ in xrange(n)]
    

    (我正在返回一个返回值列表,但您可以编写它以忽略它们,类似于您在问题中的 for 循环。)

    然后你会在哪里使用你的版本:

    threeArgs.times(7, "one", two="rawr", three="foo")
    

    您改为使用:

    times(7, threeArgs, "one", two="rawr", three="foo")
    

    【讨论】:

      猜你喜欢
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 1970-01-01
      • 2018-03-17
      • 2015-03-24
      • 2011-12-10
      • 2011-04-25
      相关资源
      最近更新 更多