有没有一种方法可以仅在您第一次调用函数时就在不使用python3创建全局变量的情况下进行计算?

时间:2018-11-05 09:32:02

标签: python python-3.x

当前,我使用以下技术:

def Myfb(param1, param2, firstTime):
    if firstTime:
        global a = compute()
        global b = compute2()
    global a
    global b
    c = doNormalExecution(param1, param2, a, b)

有没有更优雅的方式?我不喜欢创建全局变量

5 个答案:

答案 0 :(得分:2)

该技术称为记忆。 functools模块具有一个lru_cache函数,该函数可以执行您想要的操作。

from functools import lru_cache

@lru_cache(maxsize=None)
def Myfb(param1, param2):
    b = doNormalExecution(a)

python文档具有更多信息,例如maxsize是什么以及lru_cache的工作方式,以便您可以适当地实现它。

答案 1 :(得分:0)

您可以使用生成器:

def Myfb():
    a = compute()
    while True:
      param1, param2 = yield
      b = doNormalExecution(a, param1, param2)
      yield b

您在这里有一个live example

示例代码:

def compute():
  return 10

def doNormalExecution(a, b, c):
  return a + b + c

def Myfb():
    a = compute()
    while True:
      param1, param2 = yield
      b = doNormalExecution(a, param1, param2)
      yield b

f = Myfb()
next(f)
for a, b in zip(range(10), range(10)):
  print(f.send((a, b)))
  next(f)

答案 2 :(得分:0)

您可以创建一个自定义可调用对象,以保持其自己的状态:

class MyFB(object):
    _sentinel = object()

    def __init__(self):
        self._a = self._sentinel
        self._b = self._sentinel


    def __call__(self, param1, param2, reinit=False):
        if reinit or self._a is self._sentinel or self._b is self._sentinel:
            self._a = compute_a()
            self._b = compute_b()
        return doNormalExecution(param1, param2, self._a, self._b)


myfb = MyFB()

# now use `myfb` like an ordinary function

答案 3 :(得分:-2)

如果您没有将任何参数传递给函数,请使用此装饰器(我随处可见):

import functools

def lazy(func):
    """ Decorator which only actually runs a function the first time it is
    called and stores the result to be returned on later calls.

    Usage:
        @lazy
        def func_to_be_only_run_once():
            ...
    """
    FLAG = object()
    result = FLAG
    @functools.wraps(func)
    def inner():
        nonlocal result
        if result is FLAG:
            result = func()
        return result
    return inner

如果您有一个或多个更改的参数(包括self),请使用functools.lru_cache

答案 4 :(得分:-2)

这是使用闭包的一种很酷的方法。

def closure(firstTime=True):
  def Myfb():
    nonlocal firstTime
    if firstTime:
        print("First time.")
        firstTime = False
  return Myfb

myfb = closure()
myfb()
myfb()