在方案中我可以说
(define f
(let ((a (... some long computation ...)))
(lambda (args)
(...some expression involving a ...))))
然后,将仅执行一次计算a
的长计算,并且a
将在lambda内部可用。我甚至可以将set!
a
设置为其他值。
如何在Python中完成相同的工作?
我查看了许多Google对“ Python闭包”的引用,它们都引用了外部过程中的多个本地过程,这不是我想要的。
编辑:我想编写一个确定数字是否为理想平方的函数。这段代码使用二次残基到各种基数上工作,而且速度很快,平均调用昂贵的平方根函数仅占715(不到1%)的6倍:
def iroot(k, n): # newton
u, s = n, n+1
while u < s:
s = u
t=(k-1)*s+n//pow(s,k-1)
u = t // k
return s
from sets import Set
q64 = Set()
for k in xrange(0,64):
q64.add(pow(k,2,64))
q63 = Set()
for k in xrange(0,63):
q63.add(pow(k,2,63))
q65 = Set()
for k in xrange(0,65):
q65.add(pow(k,2,65))
q11 = Set()
for k in xrange(0,11):
q11.add(pow(k,2,11))
def isSquare(n):
if n % 64 not in q64:
return False
r = n % 45045
if r % 63 not in q63:
return False
if r % 65 not in q65:
return False
if r % 11 not in q11:
return False
s = iroot(2, n)
return s * s == n
我想在isSquare函数中隐藏q64,q63,q65和q11的计算,因此没有其他代码可以修改它们。我该怎么办?
答案 0 :(得分:3)
典型的Python闭包加上函数是这种语言的一等公民这一事实,几乎就像您要的一样:
def f(arg1, arg2):
a = tremendously_long_computation()
def closure():
return a + arg1 + arg2 # sorry, lack of imaginantion
return closure
在这里,对f(arg1, arg2)
的调用将返回一个函数,该函数在a
处关闭并已经计算。唯一的区别是a
是只读的,因为闭包是使用静态程序的文本构造的(但是,可以通过使用可变容器的难看的解决方案来避免这种情况)。
对于Python 3,后者似乎可以通过nonlocal
关键字来实现。
编辑:出于您的目的,缓存decorator似乎是最佳选择:
import functools
def memoize(f):
if not hasattr(f, "cache"):
f.cache = {}
@functools.wraps(f)
def caching_function(*args, **kwargs):
key = (args, tuple(sorted(kwargs.items())))
if key not in f.cache:
result = f(*args, **kwargs)
f.cache[key] = result
return f.cache[key]
return caching_function
@memoize
def q(base):
return set(pow(k, 2, base) for k in xrange(0, base))
def test(n, base):
return n % base in q(base)
def is_square(n):
if not test(n, 64):
return False
r = n % 45045
if not all((test(r, 63), test(r, 65), test(r, 11))):
return False
s = iroot(2, n)
return s * s == n
这样,q(base)
每base
才精确计算一次。哦,您也可以将iroot
和is_square
设置为可缓存的!
当然,我对缓存装饰器的实现容易出错,并且不会照顾它消耗的内存-最好使用functools.lru_cache
(至少在Python 3中) ,但可以很好地了解发生了什么。