如果一个操作的结果在代码中出现两次,python会记住它吗?

如果一个操作的结果在代码中出现两次,python会记住它吗?,python,performance,Python,Performance,我一直在用Python开发一个数独解算器,在尝试提高性能时出现了以下问题: 如果在整个代码中必须多次执行相同的计算,python是否还记得计算的结果?示例:比较以下2位代码: if get_single(foo, bar) is not None: position = get_single(foo, bar) single = get_single(foo, bar) if single is not None: position = single 这两段代码的性能是否相

我一直在用Python开发一个数独解算器,在尝试提高性能时出现了以下问题:

如果在整个代码中必须多次执行相同的计算,python是否还记得计算的结果?示例:比较以下2位代码:

if get_single(foo, bar) is not None:
    position = get_single(foo, bar)


single = get_single(foo, bar)
if single is not None:
    position = single

这两段代码的性能是否相同,或者第二段代码的性能更快,因为计算只执行一次?

否,Python不会自动记住函数调用或其他计算。一般来说,如果它真的想象到,如果对random.randrange(6)的每次调用都返回与第一次调用相同的值,那将是非常糟糕的


然而,在有用的地方,明确地让它记住对特定函数的调用并不困难。这通常被称为“记忆化”

请参阅文档中的decorator,以了解stdlib中内置的一个很好的示例。*要让它记住对
get_single(foo,bar)
的每次调用,只需像这样更改
get_single
的定义

@functools.lru_cache(maxsize=None)
def get_single(foo, bar):
    # etc.
或者,如果
get_single
是您正在导入的其他人的代码,并且无法触摸,您可以将其包装:

get_single = functools.lru_cache(maxsize=None)(othermod.get_single)
…然后调用包装器而不是模块的版本

*请注意,
lru\u缓存
是在Python 3.2中添加的。如果您使用的是2.7(或者,出于某种原因,3.0-3.1),您可以在PyPI或ActiveState上安装或找到几十个其他记忆缓存中的任何一个,甚至可以注意到
functools
docs链接到源代码,就像许多其他stdlib模块也用作示例代码一样,复制到您自己的项目中。尽管如此,IIRC还是需要对3.2代码进行一些小的修改,以便与2.7配合使用,因为它依赖于
非本地
来隐藏其内部



也就是说,即使你知道
get_single
是记忆化的,但是两次调用它仍然不是很好的风格。如果只需要执行一次,只需编写三行代码。如果您需要重复执行此操作,请编写一个包装函数来包装这三行代码或代码,然后调用该函数将比两行版本还要短。

否,Python不会自动记住函数调用或其他计算。一般来说,如果它真的想象到,如果对random.randrange(6)
的每次调用都返回与第一次调用相同的值,那将是非常糟糕的


然而,在有用的地方,明确地让它记住对特定函数的调用并不困难。这通常被称为“记忆化”

请参阅文档中的decorator,以了解stdlib中内置的一个很好的示例。*要让它记住对
get_single(foo,bar)
的每次调用,只需像这样更改
get_single
的定义

@functools.lru_cache(maxsize=None)
def get_single(foo, bar):
    # etc.
或者,如果
get_single
是您正在导入的其他人的代码,并且无法触摸,您可以将其包装:

get_single = functools.lru_cache(maxsize=None)(othermod.get_single)
…然后调用包装器而不是模块的版本

*请注意,
lru\u缓存
是在Python 3.2中添加的。如果您使用的是2.7(或者,出于某种原因,3.0-3.1),您可以在PyPI或ActiveState上安装或找到几十个其他记忆缓存中的任何一个,甚至可以注意到
functools
docs链接到源代码,就像许多其他stdlib模块也用作示例代码一样,复制到您自己的项目中。尽管如此,IIRC还是需要对3.2代码进行一些小的修改,以便与2.7配合使用,因为它依赖于
非本地
来隐藏其内部



也就是说,即使你知道
get_single
是记忆化的,但是两次调用它仍然不是很好的风格。如果只需要执行一次,只需编写三行代码。如果您需要重复执行此操作,请编写一个包装函数来包装这三行或三段代码,然后调用该函数的时间甚至比两行版本还要短。

第二个会更快,除非您特别地
记忆
d函数
get\u single
。Python通常不会“记住操作的结果”,因为不能保证任意函数总是为相同的输入提供相同的输出。第二个会更快,除非您特别地
memorize
d函数
get\u single
。Python通常不会“记住操作的结果”,因为不能保证任意函数总是为相同的输入提供相同的输出。问题实际上是,不能将
if
子句中的结果赋给变量,从而消除了额外行或调用的需要。很久以前就有人提出了
as
子句,但是冠军没有说明原因就放弃了它
as
已经爬网到了一些构造中。它在bugs.python.org上被拒绝:。这里列出了主要的反对意见:有一个更深层次的原因(Nick告诉我“感觉不对”,但也许我没有正确解释,因为我认为这是他的直觉判断和Guido的直觉判断的基础):Python中的每个语句最多变异一件事,这是最左边的事情。任何改变事物但有值的东西(比如
as
表达式)都会破坏这一点。(是的,你可以编写方法或函数来改变事物,但是按照惯例,如果可能的话,它们会返回
None
)。我认为这是Python代码比JS、Perl或Ruby更易于扫描的关键原因之一。问题实际上是不能将
if
子句中的结果分配给变量,这样就不需要额外的线路或呼叫。很久以前就有人提出了
as
子句,但是冠军没有说明原因就放弃了它
as
已经爬网到了一些构造中。它在bugs.python.org上被拒绝:。这里列出了主要的反对意见:有