2015-02-10 54 views
1

我想学习如何做科学计算面向对象的编码运行模拟访问功能;我正在使用numpy等。我创建了我的第一个课程WC_unit,它位于./classes/WC_class.py(子目录)。我在classes目录中创建了__init__.py文件(该文件为空)。当导入我的课我失去了其他模块

用于WC_unit类中的方法需要一些numpy的功能,如EXP

当我从终端运行的代码(在IPython中),采用

%run WC_class.py 

我可以生成类的实例E1 = WC_unit()我可以在其上运行的相关方法,即E1.update() 我真的不能告诉如果它的工作。我在位于的脚本test.py中写了一些外部代码。 (以上./classes)来测试我生成的对象,我尝试使用

from classes.WC_class import WC_unit 

现在,当我创建类的实例E1和运行E1.update()导入类,我得到错误信息global name 'exp' is not defined

我试过拨打from numpy import *import numpy as np,并将函数调用更改为np.exp(),并且我继续得到该错误。以为我有某种作用域与命名空间的问题或问题,我已经把这个相同的导入功能在不同的位置,包括在test.py文件,类文件WC_class.py的顶部,即使在方法:

class WC_unit: 
    def __init__(self): [assign default pars from a dict including r, dt, tau, and Iapp]... 
    def update(self): 
     from numpy import * 
     self.r += self.dt/self.tau * (-self.r + exp(self.Iapp)) 

我真的很想看看我的游戏,并弄清楚如何编写我自己的课程,并将它们与真棒计算工具一起使用。我想我想知道:

  1. 我做错了什么(可能很多,我怀疑)。我认为这是我如何导入我的课程?但也许也在班级本身范围内。

  2. 为什么我的班级在我import的时候失去了对numpy功能的访问权,但是当我在终端中像运行脚本那样运行时,

  3. 我想我也一般不明白为什么人们如此保护自己的命名空间,也就是为什么有那么多的例子说明import numpy as np和使用所有的功能np.exp(x),等我没有太多的一个计算机科学背景,所以我可以从你可以提供的任何解释中受益良多 - 文档对我来说有点神秘。

Python版本:2.7.8 | Anaconda 2.1.0(x86_64)| (默认情况下,2014年8月21日,15:21:46) [GCC 4.2.1(苹果公司建立5577)] 在Mac OSX 10.6.8

+0

停止做'从numpy的进口*'和'喜欢进口numpy'和使用'numpy.array','numpy.mean'等。这样可以防止名称空间污染,从而产生您所看到的问题。 – CoryKramer 2015-02-10 19:23:37

+0

请始终显示任何错误消息*全回溯*在你的问题 – 2015-02-10 20:37:32

回答

1

当你在打电话的IPython %run WC_class.py,你在做什么是将该源文件的内容直接加载到交互式命名空间中。因为在IPython会话中已经调用了from numpy import *,因此在当前“模块”(在本例中,这只是IPython交互式命名空间)的全局变量集内定义为exp,因此当您拨打WC_unit.update() (或WC_class.py内的其他任何地方),它会正常工作。

但是,你不要在test.py顶部做一个from numpy import *,因此当您导入WC_unit到脚本exp没有被当前模块的范围内定义(也就是现在的test脚本)。

你已经试过from numpy import *WC_unit.update()方法本身,但是这将失败,因为import * is only allowed at a module level(其实你应该已经看到了SyntaxWarning这个当你试图导入WC_unit!)。由于导入失败,exp仍是不确定的和WC_unit.update()方法会提高你所看到的NameError

什么你应该做的是有一个使用numpy的功能的任何源文件的顶部一次导入线:

import numpy as np 

然后通过np.命名空间是指任何numpy的功能。


关于你提到的第三点,主要的原因做

import numpy as np 

x = np.exp(y) # etc. 

而不是

from numpy import * 

x = exp(y) # etc. 

是后一种方法污染您的全局命名空间。

假设你已经定义了自己的函数调用exp。当你这样做from numpy import *,你会被改写自己的函数调用expnumpy.exp,所以当你再打exp(y)它可能不是你希望它是什么。例如,这正是发生在一些内置的Python功能,如sumall

print(sum.__module__) 
# __builtin__ 

from numpy import * 

print(sum.__module__) 
# numpy.core.fromnumeric 

更重要的是,这是更多或更少的不可逆的 - 一旦你做了from module import *有没有简单的方法来摆脱你已经导入到你的名字空间的东西(或者恢复你通过导入顶部导入的任何旧模块或变量)。

只要你保留所有的在它自己单独的命名空间的每个模块的内容没有命名空间冲突的风险,并没有关于其中每个函数或类来自歧义。按照惯例,我们用np来指代命名空间numpy的,pltmatplotlib.pyplot

+0

谢谢!我不知道这到底是什么回事,但我肯定能学习一些关于类和对象是如何工作的,并打破东西分解成更小的块。在学习如何写作时,我可能会问更多的哲学类型的问题,我感谢你的彻底和直接的答案。如果任何人都可以将我链接到任何关于如何使用类开发模拟的教程,我很乐意阅读它们。特别是我无法弄清楚如何构建我的文件...模块... – steeles 2015-02-11 00:29:39