def once(fcn):
func = [fcn]
def inner(*args):
return func.pop()(*args) if len(func) else None
return inner
def add(a,b):
return a+b
oneAddition = once(add)
print(oneAddition(2,2)) # 4
print(oneAddition(2,2)) # None
print(oneAddition(12,200)) # None
print(once(add)(2,2)) # 4
print(once(add)(2,2)) # Should return None, returns 4
print(once(add)(12,200)) # Should return None, returns 212
因此,此嵌套函数的目的是跟踪调用外部函数的次数。它仅在首次调用时返回添加结果。之后,无论何时调用,它都将返回None。
真正引起我兴趣的是oneAddition = once(add)-> oneAddition(2,2)和一次(add)(x,y)的行为不同。
在第二种方法中,似乎也执行了外部函数。使用第一种方法,外部函数仅在构造时执行(非常类似于装饰器)。
有人可以向我解释为什么吗?非常感谢。
P.S。我知道使用非本地var将是一个更合适的解决方案,我只是加入了 list-in-a-list 方法,因为它看起来很酷(可以在线找到)。
答案 0 :(得分:2)
每次once(add)
调用都会创建一个新的inner
闭包,并带有一个新的func
引用,并将其返回。因此,您后三个print
中的每一个都在完全独立的func
列表上进行操作,从而输出。
一种简单的查看方法是查看字节码:
>>> dis(once)
2 0 LOAD_FAST 0 (fcn)
2 BUILD_LIST 1
4 STORE_DEREF 0 (func)
3 6 LOAD_CLOSURE 0 (func)
8 BUILD_TUPLE 1
10 LOAD_CONST 1 (<code object inner at 0x10c64c300, file "<stdin>", line 3>)
12 LOAD_CONST 2 ('once.<locals>.inner')
14 MAKE_FUNCTION 8
16 STORE_FAST 1 (inner)
5 18 LOAD_FAST 1 (inner)
20 RETURN_VALUE
请注意,once
在每次调用(func
)上都会建立一个 new BUILD_LIST
列表,而该列表又被返回的闭包使用({ {1}}。
另一种查看方法是在MAKE_FUNCTION
内打印id(func)
:
inner()
请注意,这些ID不同。