【问题标题】:Python: Redefining function from within the functionPython:从函数内部重新定义函数
【发布时间】:2011-09-18 02:26:12
【问题描述】:

我有一些昂贵的函数 f(x),我只想计算一次,但被频繁调用。本质上,第一次调用该函数时,它应该计算一系列 x 的值,因为无论如何它都会被积分,然后用样条插值,并以某种方式缓存系数,可能在一个文件中进一步使用。

我的想法是执行以下操作,因为它很容易实现。第一次调用该函数时,它会做一些事情,然后重新定义自己,然后再做其他事情。但是,它不能按预期工作,通常可能是不好的做法。

def f():
    def g():
        print(2)
    print(1)
    f = g
f()
f()

预期输出:

1
2

实际输出:

1
1

在 f() 之外定义 g() 没有帮助。为什么这不起作用?除此之外,我现在能想到的唯一解决方案是使用一些全局变量。或者为此编写一个类是否有意义?

【问题讨论】:

    标签: python


    【解决方案1】:

    这太复杂了。相反,使用记忆:

    def memoized(f):
        res = []
        def resf():
           if len(res) == 0
               res.append(f())
           return res[0]
        return resf
    

    然后简单

    @memoized
    def f():
       # expensive calculation here ...
       return calculated_value
    

    在 Python 3 中,您可以将 memoized 替换为 functools.lru_cache

    【讨论】:

    • +1: memoizationdecoration,在允许装饰的 Python 版本中,是要走的路。规范示例here.
    • dict 是不可散列的,你不觉得有问题吗?
    • @juanchopanza 哎呀,是的。删除了参数,因为在这个例子中它们是不必要的。
    • @phihag 我希望有一个简单的内置解决方案来记忆 **kwargs!
    • @juanchopanza 好吧,您可以随时将这些项目转换为 frozenset,但只要 args/kwargs 中的值不可散列,它就会崩溃。
    【解决方案2】:

    只需在f函数的开头加上global f,否则python会创建一个局部f变量。

    【讨论】:

      【解决方案3】:

      在 f 的作用域内改变 f 不会影响函数外,如果你想改变 f,你可以使用 global:

      >>> def f():
      ...     print(1)
      ...     global f
      ...     f=lambda: print(2)
      ... 
      >>> f()
      1
      >>> f()
      2
      >>> f()
      2
      

      【讨论】:

        【解决方案4】:

        您可以使用memoizationdecoration 来缓存结果。查看示例here。可以在here 找到一个单独的关于记忆的问题,它可能被证明是有用的。

        【讨论】:

          【解决方案5】:

          您所描述的是发明缓存的那种问题。为什么不只是有一个缓冲区来保存结果?在进行昂贵的计算之前,检查缓冲区是否已经被填满;如果是,则返回缓冲结果,否则,执行计算,填充缓冲区,然后返回结果。无需为此花心思在自修改代码上。

          【讨论】:

          • 他说的是实话。阿门(+1)。
          猜你喜欢
          • 1970-01-01
          • 2023-03-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-16
          • 1970-01-01
          • 2011-01-20
          相关资源
          最近更新 更多