def fib(n):
if n <= 1:
return n
else:
return fib(n - 2) + fib(n - 1)
def count(f):
def counted(*args):
counted.call_count += 1
return f(*args)
counted.call_count = 0
return counted
>>> fib = count(fib)
>>> fib(5)
5
>>> fib.call_count
15
>>> counted.call_count
NameError
我知道fib
现在实际上是counted
。但是,我不明白为什么当我想调用counted.call_count
时,我必须调用fib.call_count
。你知道吗
我认为counted
是类Function
的一个实例。但是counted.call_count
到底是什么意思?你知道吗
更具体地说,我不理解在代码class ****:
之外定义的属性。在这种情况下,定义属性就像self.call_count
更清晰,因为我可以理解self
来引用实例。在我的例子中,看起来counted.call_count
中的counted
和self.call_count
中的self
一样,但是是吗?你知道吗
思考python解释器是如何工作的,可能会帮助您理解这里发生了什么。当源代码通过lexer并转化为字节码时,我们可以看到“load”和“store”命令的引用,表明解释器主要作为基于堆栈的机器工作:
我们还可以看到,
call_count
属性被绑定到创建的新代码对象,但是名称:counted
被显式取消引用,因为它不再在作用域中,只返回代码对象。你知道吗这里的问题是
counted
函数在主程序代码中没有被调用counted
,它被称为fib
。(count
返回counted
,通过赋值将其绑定到fib
),因此应该使用这个名称。你知道吗你对修饰函数名的依赖有点脆弱。你会发现你依赖这个名字。如果您将调用代码改为
您将看到它只计算外部调用。你知道吗
你实际上是在写一个装饰师,尽管你可能不知道。一种更为传统的写作方式可能是
这样就不需要手动包装函数(decorator语法只是为您进行调用),您只需编写
问题是,您只能调用此修饰函数一次,除非您考虑到在进一步调用时计数会继续累积:
这是可以接受的。否则,可能需要进一步的复杂性。你知道吗
相关问题 更多 >
编程相关推荐