gpt4 book ai didi

python - 递归闭包(函数发生器)

转载 作者:太空狗 更新时间:2023-10-30 02:34:10 25 4
gpt4 key购买 nike

我一直在学习函数式编程,并且想到了组装数学运算符的想法。counting -> addition -> multiplication -> power -> ... 自然而然地出现了简单和最天真的代码来表达这个并且它有效!问题是我真的不知道为什么它工作得这么好,输出这么大。

问题是:这个函数的复杂度是多少?

代码在 python 中:

def operator(d):
if d<=1:
return lambda x,y:x+y
else:
return lambda x,y:reduce(operator(d-1),(x for i in xrange(y)))


#test
f1 = operator(1) #f1 is adition
print("f1",f1(50,52)) #50+52

f2 = operator(2) #f2 is multiplication
print("f2",f2(2,20)) #2*20

f3 = operator(3) #f3 is power, just look how long output can be
print("f3",f3(4,100)) #4**100

f4 = operator(4) #f4 is superpower, this one does not work that well
print("f4",f4(2,6)) #((((2**2)**2)**2)**2)**2

f5 = operator(5) #f5 do not ask about this one,
print("f5",f5(2,4)) #

输出(即时):

('f1', 102)
('f2', 40)
('f3', 1606938044258990275541962092341162602522202993782792835301376L)
('f4', 4294967296L)
('f5', 32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656L)

最佳答案

反汇编告诉您这里没有应用神奇的优化,它实际上只是对 genexpr 的减少。 Python 似乎可以胜任这项任务,即使它会让您感到惊讶。

>>> import dis
>>> dis.dis(f3)
5 0 LOAD_GLOBAL 0 (reduce)
3 LOAD_GLOBAL 1 (operator)
6 LOAD_DEREF 1 (d)
9 LOAD_CONST 1 (1)
12 BINARY_SUBTRACT
13 CALL_FUNCTION 1
16 LOAD_CLOSURE 0 (x)
19 BUILD_TUPLE 1
22 LOAD_CONST 2 (<code object <genexpr> at 0x7f32d325f830, file "<stdin>", line 5>)
25 MAKE_CLOSURE 0
28 LOAD_GLOBAL 2 (xrange)
31 LOAD_FAST 1 (y)
34 CALL_FUNCTION 1
37 GET_ITER
38 CALL_FUNCTION 1
41 CALL_FUNCTION 2
44 RETURN_VALUE

如果您专门查看您的 f5(2,4) 调用,它实际上并没有执行那么多操作:

>>> counter = 0
>>> def adder(x, y):
... global counter
... counter += 1
... return x + y
...
>>> def op(d):
... if d <= 1: return adder
... return lambda x,y:reduce(op(d-1),(x for i in xrange(y)))
...
>>> op(5)(2,4)
32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656L
>>> counter
65035
>>> counter = 0
>>> op(3)(4,100)
>>> counter
297

65k 的加法,更不用说求幂的 297 次了,对于经过滑稽优化的现代 CPU 来说甚至都不值一提,所以眨眼之间就完成也就不足为奇了。尝试增加其中一个参数,看看它如何非常快速地达到快速评估的边界。

顺便说一下,operator 是一个内置模块,您不应该这样命名您自己的函数。

关于python - 递归闭包(函数发生器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9813791/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com