类似于Python中的devar

时间:2013-10-06 22:47:31

标签: python python-interactive

在编写Python代码时,我经常发现自己想要获得类似于Lisp的defvar的行为。基本上,如果某个变量不存在,我想创建它并为其分配一个特定的值。否则,我不想做任何事情,特别是,我不想覆盖变量的当前值。

我环顾四周,发现了这个建议:

try:
    some_variable
except NameError:
    some_variable = some_expensive_computation()

我一直在使用它并且工作正常。但是,对我而言,这样的代码看起来并非正常。代码是四行,而不是Lisp中需要的代码,它需要异常处理来处理那些不是“特殊”的东西。

背景是我正在进行交互式开发。我经常执行我的Python代码文件,因为我改进了它,而且每次我都不想运行some_expensive_computation()。我可以安排每次启动一个新的Python解释器时手动运行some_expensive_computation(),但我宁愿做一些自动化的事情,特别是这样我的代码可以非交互式运行。一个季节Python程序员将如何实现这一目标?

我正在使用WinXP和SP3,Python 2.7.5通过Anaconda 1.6.2(32位),并在Spyder中运行。

5 个答案:

答案 0 :(得分:2)

依赖于具有意义的变量的存在或不存在通常是一个坏主意。而是使用sentinel值来指示变量未设置为适当的值。 None是此类哨兵的常见选择,但如果这可能是您昂贵计算的可能输出,则可能不合适。

所以,而不是你当前的代码,做这样的事情:

# early on in the program
some_variable = None

# later:
if some_variable is None:
    some_variable = some_expensive_computation()

# use some_variable here

或者,None可能是重要值的版本:

_sentinel = object()
some_variable = _sentinel # this means it doesn't have a meaningful value

# later
if some_variable is _sentinel:
    some_variable = some_expensive_computation()

答案 1 :(得分:2)

很难说出您更关心哪个,特定语言功能或持续会话。既然你说:

  

背景是我正在进行交互式开发。我经常执行我的Python代码文件,因为我改进了它,而且每次我都不想运行some_expensive_computation()。

您可能会发现IPython提供了一个令您满意的持久互动环境。

答案 2 :(得分:1)

不要在Python中编写Lisp,只要想想你正在尝试做什么。你想避免两次调用昂贵的函数并让它运行两次。你可以编写你的函数:

def f(x):
    if x in cache:
        return cache[x]

    result = ...
    cache[x] = result

    return result

或者使用Python的装饰器,只需使用另一个为您处理缓存的函数来装饰该函数。 Python 3.3附带functools.lru_cache,它就是这样:

import functools

@functools.lru_cache()
def f(x):
    return ...

PyPi for 2.7中有相当多的memoization库。

答案 3 :(得分:1)

对于您提供的用例,使用try ... except保护似乎是一种很好的方法:您的代码依赖于先前执行脚本的剩余变量。

但我同意这不是一个很好的概念实现"这里是一个默认值,除非变量已经设置,否则使用它#34;。 Python并不直接支持变量,但它确实有一个字典键的默认设置器:

myvalues = dict()
myvalues.setdefault("some_variable", 42)
print some_variable    # prints 42

setdefault的第一个参数必须是字符串,其中包含要定义的变量的名称。

如果您有一个复杂的设置系统和默认设置(如emacs),您可能会将系统设置保存在自己的字典中,因此这就是您所需要的。在您的情况下,您还可以在全局变量(仅)上直接使用setdefault,借助内置函数globals()返回可修改的字典:

globals().setdefault("some_variable", 42)

但我建议为持久变量使用字典(可以使用try... except方法有条件地创建它)。它保持东西清洁,看起来更像...... pythonic。

答案 4 :(得分:0)

让我试着总结一下我在这里学到的东西:

  1. 在Python中使用异常处理进行流控制很好。我可以做一次设置一个dict,我可以存储我想要的东西。
  2. 有针对某种形式的持久性设计的库和语言功能;这些可以为某些应用提供“高路”解决方案。搁置模块在这里是一个显而易见的候选者,但我会广泛地解释“某种形式的持久性”,包括@Blender建议使用memoization。