【问题标题】:python: import numpy as np from outer code gets lost within my own user defined modulepython: import numpy as np from external code 在我自己的用户定义模块中丢失
【发布时间】:2015-04-11 07:03:30
【问题描述】:

我正在为科学计算进行模拟,而且我几乎总是想在交互式解释器中查看模拟的输出。我正在尝试编写类来定义模拟对象(神经群体),我想通过在 ipython 中调用脚本%run test_class_WC.py 来正式化我对这些类的测试。由于包含该类的模块/文件在我尝试调试它/添加功能时正在发生变化,因此我每次都重新加载它。

./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

所以我马上使用 reload 来确保我已经加载了最新版本的模块,所以我有最新的类定义——我敢肯定这很笨重(而且也许更险恶?),但它为我省去了一些麻烦,因为我不用再做%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

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

我也愿意接受有关改进我的工作流程和文件结构的建议,因为它似乎不是特别 Python 的。如果这有助于任何人理解,我的背景是 MATLAB。我正在 SublimeText2 中编辑我的 .py 文件。抱歉,代码不是很少,我一直很难重现这个问题。

【问题讨论】:

  • 你需要在WC_class.py顶部import numpy as np

标签: python numpy namespaces scope


【解决方案1】:

正确的方法是在子模块的顶部也使用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

【讨论】:

    【解决方案2】:

    在 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,请使用最后一行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-14
      • 2016-02-10
      • 2014-11-02
      • 2022-11-03
      • 2023-02-25
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      相关资源
      最近更新 更多