在Python中关闭变量

2024-09-30 20:28:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我可以这么说

(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的计算,这样其他代码就不能修改它们了。我该怎么做?你知道吗


Tags: 函数inaddfalseforreturnifnot
1条回答
网友
1楼 · 发布于 2024-09-30 20:28:19

一个典型的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是只读的,因为闭包是用静态程序的文本构造的(然而,这可能是用丑陋的解决方案来避免的,这些解决方案涉及到使用可变的容器)。你知道吗

至于python3,后者似乎可以通过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。哦,你还可以让irootis_square缓存也可以!你知道吗

当然,我的缓存修饰符实现很容易出错,并且不会更好地利用^{}(至少在python3中是这样),但它很好地理解了所发生的事情。你知道吗

相关问题 更多 >