代码之家  ›  专栏  ›  技术社区  ›  Fractale

有没有一种方法可以只在第一次调用函数时计算某个东西而不在python3中创建全局函数?

  •  1
  • Fractale  · 技术社区  · 7 年前

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

    有更优雅的方式吗?我不喜欢创造全球性的

    5 回复  |  直到 7 年前
        1
  •  2
  •   Ananth    7 年前

    这种技术叫做记忆。functools模块有一个 lru_cache

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

        2
  •  0
  •   Netwave    7 年前

    可以使用生成器:

    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)
    
        3
  •  0
  •   bruno desthuilliers    7 年前

    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
    
        4
  •  -2
  •   FHTMitchell    7 年前

    如果您不向函数传递任何参数,请使用此装饰器(我让它到处都是):

    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

        5
  •  -2
  •   Silver    7 年前

    这里有一个很酷的使用闭包的方法。

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