2015-02-11 71 views
1

我正在做科学计算的模拟,而且我几乎总是想要在交互式解释器中查找输出我的模拟。我试图编写类来定义模拟对象(神经人群),我想通过在ipython中调用脚本%run test_class_WC.py来正式确定我对这些类的测试。由于包含该类的模块/文件在我尝试调试/添加功能时发生了变化,因此我每次都要重新加载它。python:import numpy as np from external code gets in my own user defined module

./test_class_WC.py:

import WC_class # make sure WC_class exists 
reload(WC_class) # make sure it's the most current version 
import numpy as np 

from WC_class import WC_unit # put the class into my global namespace? 

E1 = WC_unit(Iapp=100) 
E1.update() # see if it works 
print E1.r 

所以马上我使用重载使蝙蝠肯定我明白了加载模块的最新版本,所以我有最新鲜的类definition--我敢肯定,这是笨重赫克(也许更险恶?),但它节省了我做%run WC_class.py和不得不做一个单独的呼叫%run test_WC.py

和./WC_class一些麻烦:

class WC_unit: 

    nUnits = 0 
    def __init__(self,**kwargs): 
     self.__dict__.update(dict(  # a bunch of params 
       gee = .6,    # i need to be able to change 
       ke=.1,the=.2,   # in test_class_WC.py 
       tau=100.,dt=.1,r=0.,Iapp=1.), **kwargs) 
     WC_unit.nUnits +=1 

    def update(self): 
     def f(x,k=self.ke,th=self.the): # a function i define inside a method 
      return 1/(1+np.exp(-(x-th)/k)) # using some of those params 
     x = self.Iapp + self.gee * self.r 
     self.r += self.dt/self.tau * (-self.r + f(x)) 

WC_unit基本上定义了一堆默认参数,并定义了使用基本欧拉积分进行更新的ODE。我希望test_class_WC建立含有NP一个全局命名空间(和WC_unit和WC_class)

当我运行它,我得到以下错误:

In [14]: %run test_class_WC.py 
--------------------------------------------------------------------------- 
NameError         Traceback (most recent call last) 
/Users/steeles/Desktop/science/WC_sequence/test_class_WC.py in <module>() 
     8 
     9 E1 = WC_unit(Iapp=100) 
---> 10 E1.update() 
    11 
    12 # if bPlot: 

/Users/steeles/Desktop/science/WC_sequence/WC_class.py in update(self) 
    19       return 1/(1+np.exp(-(x-th)/k)) 
    20     x = self.Iapp + self.gee * self.r 
---> 21     self.r += self.dt/self.tau * (-self.r + f(x)) 
    22 
    23   # @class_method 

/Users/steeles/Desktop/science/WC_sequence/WC_class.py in f(x, k, th) 
    17   def update(self): 
    18     def f(x,k=self.ke,th=self.the): 
---> 19       return 1/(1+np.exp(-(x-th)/k)) 
    20     x = self.Iapp + self.gee * self.r 
    21     self.r += self.dt/self.tau * (-self.r + f(x)) 

NameError: global name 'np' is not defined 

现在我可以只导入numpy的解决这个问题作为np在WC_class模块的顶部,或者甚至在test_class_WC中执行from numpy import exp,并将update()方法更改为包含exp()而不是np.exp()...但我没有试图这样做,因为它很容易,我想了解所有这些命名空间/模块的东西如何工作,所以我不再是一个蟒蛇白痴。为什么np在WC_unit命名空间中迷路了?是因为我正在处理两个不同的文件/模块?在函数内调用np.exp是否与它有关?

对于改进我的工作流程和文件结构,我也很乐于提供建议,因为它似乎不是特别pythonic。如果这有助于任何人理解,我的背景是在MATLAB中。我正在编辑SublimeText2中的.py文件。抱歉,代码不是非常小,我一直在很难再现问题。

+0

您需要在'WC_class.py'的顶部将'numpy导入为np' – 2015-02-11 02:15:52

回答

2

正确的方法是在子模块的顶部也执行import numpy as np。这里的原因:

要注意的关键问题是,在Python,global实际上是指“在模块级共享”,并且每个模块的命名空间存在明显的相互除了当一个模块明确地从另一个出口模块。一个导入的模块肯定无法接触到它的'父'模块的命名空间,这可能是所有事情都考虑过的一件好事,否则你将拥有模块,它们的行为完全取决于导入模块的变量。

所以当堆栈跟踪说global name 'np' is not defined,它是在模块级别谈论它。默认情况下,Python不允许WC_Class模块在其父模块中访问对象。

(顺便说一句,effbot有quick note on how to do inter-module globals

需要注意的是,即使你在你的代码中各个模块的多个import numpy as np,该模块实际上只被载入另一个关键的事情(即执行)一次。加载后,模块(本身就是Python对象)可以在字典sys.modules中找到,并且如果此字典中已存在模块,则任何import module_to_import语句都只允许导入模块访问名称空间module_to_import中的名称。因此,将import numpy as np分散在代码库中的多个模块中并不是浪费。

编辑:在更深的挖掘,effbot有even deeper (but still pretty quick and simple) exploration of what actually happens in module imports。要深入探讨该主题,您可能需要检查在Python 3文档中新添加的import system discussion

0

在Python中导入每个模块所需的每个模块是正常的。不要指望任何'全球'进口。事实上并没有这样的事情。有一个例外。我在

Do I have to specify import when Python script is being run in Ipython?

%run -i myscript运行在IPython中的互动命名空间脚本

发现。因此,对于快速测试脚本,这可以节省一大堆导入。

我没有看到这三重进口

import WC_class # make sure WC_class exists 
reload(WC_class) # make sure it's the most current version 
... 
from WC_class import WC_unit 

的需求。如果你是从WC_class使用只需使用的最后一行。

相关问题