Python - 包装函数的范围

时间:2013-12-06 16:01:51

标签: python closures wrapper

目标是包装一个函数或方法,并使用包装函数独有的包装器来携带数据。

作为一个例子 - 假设我有方法myThing的对象foo。我想用myThing.foo包裹myWrapper,并且(作为示例)我希望能够计算myThing.foo实际调用的次数。

到目前为止,我发现唯一有效的方法是只为对象添加一个属性 - 但这感觉有点笨拙。

class myThing(object):
    def foo(self):
        return "Foo called."

def myWrap(some_func):
    def _inner(self):
        #a wild kludge appears!
        try:
            self.count += 1
        except AttributeError:
            self.count = 0
        return some_func(self)
    return _inner

Stick = myThing()
myThing.foo = myWrap(myThing.foo)
for i in range(0, 10):
    Stick.foo() ##outputs "Foo called." 10 times

Stick.count # the value of Stick.count

所以,这实现了目标,事实上如果有myThing的多个实例,那么每个实例都会跟踪它自己的self.count值,这是我预期目标的一部分。但是,我不确定为myThing的每个实例添加属性是实现此目的的最佳方法。例如,如果我要为不属于对象或类的函数编写包装器,则向不存在的对象添加属性将不会执行任何操作。

也许在我理解包装方法或函数时实际发生的事情上存在漏洞。我知道可以在闭包中维护某种静态数据,如下例所示:

def limit(max_value):
    def compare(x):
        return x > max_value
    return compare

isOverLimit = limit(30)
isOverLimit(45) #returns True
isOverLimit(12) #returns False

alsoOver = limit(20)
alsoOver(25) # returns True
isOverLimit(25) # returns False

第二个示例证明它不仅仅是修改limit的原始实例,并且isOverLimit继续按照创建第二个alsoOver之前的方式执行操作。所以我觉得包装器有一种方法可以随身携带增量变量,而我只是遗漏了一些明显的东西。

1 个答案:

答案 0 :(得分:1)

似乎这是Counting python method calls within another method

的欺骗

简短的回答是在要计算的方法/函数上使用装饰器,并让装饰器将计数器存储为函数属性。请参阅我链接的问题中的答案。