【问题标题】:Python return one-liner behaves differently than multiple liner codePython 返回单行代码的行为与多行代码不同
【发布时间】:2019-08-09 00:28:30
【问题描述】:

我正在练习用 python 生成斐波那契数列,并遵循How do I print a fibonacci sequence to the nth number in Python? 的记忆示例。

然后我遇到了一个有趣的区别,即使用 return one-liner 而不是。例如,示例代码如下所示。在第一个示例中,我们没有使用 return one-liner,它运行得非常快,而在第二个示例中,我们使用了 return one-liner,它运行得非常慢。

他们不应该是一样的吗?

没有单行

def memoize(func):
    memo = dict()
    def decorated(n):
        if n not in memo:
            memo[n] = func(n)
        return memo[n]

    return decorated

@memoize
def fib(n):
    if n<=1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

print([ fib(i) for i in range(100,110)]) # runs very fast

单线返回

def memoize(func):
    memo = dict()
    def decorated(n):
        return func(n) if n not in memo else memo[n]

    return decorated

@memoize
def fib(n):
    if n<=1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

print([ fib(i) for i in range(100,110)]) # very slow

问题
他们不应该是一样的吗?
为什么返回一班轮比另一班慢得多?
我们可以用不同的措辞写一个单行,以使其同样快吗?

【问题讨论】:

  • 单行不修改memo的内容。
  • 2.第二个速度较慢,因为您大概不会在 memo 中保存任何内容。
  • 正确的单行应该类似于return memo[n] if n in memo else memo.setdefault(n, func(n))。 (如果查找实际上会成功,则条件表达式会阻止评估 func(n)。)
  • 如果您关心代码行,我可以将您的整个 memorize 函数压缩为一行:from functools import lru_cache as memorize。这是用 c 编写的,比在 python 中重现的任何东西都要快得多。 docs.python.org/3/library/functools.html#functools.lru_cache
  • @astro123 文档说你必须使用@lru_cache(maxsize=&lt;integer value or None&gt;) 而不是简单的@lru_cache

标签: python


【解决方案1】:

这个

    if n not in memo:
        memo[n] = func(n)
    return memo[n]

不一样
    return func(n) if n not in memo else memo[n]

单行不修改备忘录的内容。如果您想将苹果与苹果进行比较,请尝试:

    if n not in memo:
        return func(n)
    return memo[n]

为了优化你的单行,并保存字典值,你应该将单行更改为:

    return memo[n] if n in memo else memo.setdefault(n, func(n))

除了了解 memoize 的工作原理之外,您还应该考虑使用 functools lru_cache's memoize,它“用 C 语言编写,比用 Python 重现的任何东西都要快得多。”

向 meowgoesthedog、chepner 和 FHTMitchell 致敬。

【讨论】:

  • 大声笑,您没有展示如何正确优化单排,而是展示了如何取消优化 3 排。
  • @Barmar 这是python。不鼓励积极减少行数。
  • @FHTMitchell 编写memoize 函数的意义在于,您只需编写一次就忘记它——简洁地编写它没有任何好处。
猜你喜欢
  • 1970-01-01
  • 2015-09-02
  • 2013-07-17
  • 2021-12-02
  • 2014-07-14
  • 2021-03-31
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
相关资源
最近更新 更多