2015-04-02 84 views
1

我在我的研究中广泛使用IPython笔记本。我发现他们是一个很棒的工具。避免python范围错误的策略

但是,不止一次,我被来自变量范围的微妙错误所困扰。例如,我会做一些探索性的分析:

foo = 1 
bar = 2 
foo + bar 

我决定foo + bar是我的目的,一个有用的算法,所以我将其封装在一个功能,使其更容易应用到更广泛的投入:

def the_function(foo, bar): 
    return foo + bar 

不可避免地,某处向下行,构建从地面工作流起来后,我将有一个错字某处(例如def the_function(fooo, bar):)使得在所使用的全局变量(和/或经修饰的)函数调用。这会导致看不见的副作用并导致虚假结果。但是因为它通常会返回结果,所以很难找到问题实际发生的位置。

现在,我认识到这种行为是我经常故意使用的一个特性(为了方便,或者必要时,即函数闭包或装饰器)。但是当我不断遇到错误时,我想我需要一个更好的策略来避免这些问题(当前策略=“小心”)。

例如,一种策略可能总是在本地变量名称前加'_'。但我很好奇,如果没有其他策略 - 甚至是“pythonic”策略,或社区鼓励策略。

我知道python 2.x在某些方面与python 3.x的区别不同 - 我使用python 3.x.

此外,策略应该考虑科学计算的交互性,就像在IPython Notebook场地中使用的那样。

想法?

编辑:更具体地说,我在寻找IPython Notebook策略。

+0

使用模块并避免全局性 – dawg 2015-04-02 17:09:06

回答

0

最后,我自己解决了这个问题。它建立在迄今为止给出的两个答案上。

你可以找到我的解决方案,这是一个神奇的细胞扩展,在GitHub上:https://github.com/brazilbean/modulemagic

简单地说,这个扩展让你在笔记本创造%%模块细胞的能力。这些单元格保存为一个文件并导入到会话中。它有效地完成了@shadanan所建议的内容,但允许你将所有的工作放在同一个地方(方便,并符合笔记本在同一地点提供代码和结果的理念)。

因为导入过程会对代码进行沙箱处理,所以它解决了激发我原始问题的所有示波器遮蔽错误。它也涉及很少或没有开销 - 没有重命名变量,打开其他编辑器等。

1

我很想把这个问题标记为过于宽泛,但也许下面的内容会帮助你。

当你决定在函数中包装一些有用的代码时,写一些测试。如果你认为代码很有用,你必须用一些例子来使用它。先写测试,免得你'忘记'。

我对库模块的个人策略是在if __name__ == '__main__':语句中运行测试,无论测试代码是在同一个文件中还是在不同的文件中。在编程会话期间,我也执行文件多次运行测试,每改变一小部分(在Idle或类似IDE中微不足道)。

使用代码检查程序,它将捕获一些错字错误。 “'fooo'设置但从未使用过”。

保持跟踪特定种类的错误制作,分析它们并思考个人对策,或者至少学会识别症状。

看看你的例子,当你写一个函数时,不要为全局对象和参数使用相同的名字。在你的例子中,删除或更改全局'foo'和'bar'或使用其他参数名称。

+0

我很欣赏这些建议。因为我在IPython Notebook中工作,所以您提到的IDE工具不可用。我认为你说得对,单元测试是避免我描述的错误的好策略 - 我会考虑的。 – 2015-04-02 20:06:15

+0

使用不同的变量名称与我的问题中的示例策略基本相同。在避免与全局名称空间冲突的同时,预先添加'_'可以保持变量的目的清晰;然而,很容易忘记或忽略(导致原来的问题)。重命名所有变量可以避免这种情况,但缺点是您必须为您迄今为止开发的概念创建新名称 - 最明显的名称已被选中(在全局名称空间中使用),所以现在您已经混淆了/功能中的一次性名字。 – 2015-04-02 20:09:04

1

我建议你分开你的顾虑。为了进行探索性分析,请将代码写入iPython笔记本中,但是如果您确定有一些有用的功能,请打开一个编辑器并将其放入一个python文件中,然后导入该文件。

您可以使用iPython magics自动重新载入您导入的内容。所以一旦你在iPython中测试了它们,你可以简单地将它们复制到你的模块中。这样,您的功能范围就与笔记本电脑隔离开来。另外一个好处是,当你准备好在无头环境中运行时,你已经将你的整个代码库放在一个地方。