Python 导入类时,我无法从其他模块访问函数

Python 导入类时,我无法从其他模块访问函数,python,numpy,import,scope,Python,Numpy,Import,Scope,我试图学习如何为运行模拟的科学计算进行面向对象的编码;我正在使用numpy等。我已经创建了我的第一个类,WC\u unit,它位于/classes/WC\u class.py(一个子目录)。我已经在类目录中创建了一个\uuuu init\uuuuuuuuuupy文件(该文件为空) WC\u单元类的方法需要一些numpy函数,如exp 当我从终端运行代码(在ipython中)时,使用 %run WC_class.py 我可以生成类E1=WC\u unit()的实例,并可以在其上运行相关的方法,即

我试图学习如何为运行模拟的科学计算进行面向对象的编码;我正在使用numpy等。我已经创建了我的第一个类,
WC\u unit
,它位于
/classes/WC\u class.py
(一个子目录)。我已经在
目录中创建了一个
\uuuu init\uuuuuuuuuupy
文件(该文件为空)

WC\u单元
类的方法需要一些numpy函数,如exp

当我从终端运行代码(在ipython中)时,使用

%run WC_class.py
我可以生成类
E1=WC\u unit()
的实例,并可以在其上运行相关的方法,即
E1.update()
我真的不知道它是否有效。我在位于的脚本
test.py
中编写了一些外部代码。(上图
/classes
)来测试我正在生成的对象,并尝试使用

from classes.WC_class import WC_unit
现在,当我创建类的实例
E1
并运行
E1.update()
时,我得到错误消息
全局名称“exp”未定义

我尝试从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))
我真的很想改进我的游戏,弄清楚如何编写自己的类,并将它们与很棒的计算工具一起使用。我想我想知道:

  • 我做错了什么(我怀疑可能很多)。我想这和我如何导入我的课程有关?但也许也包括课堂本身的范围界定

  • 为什么我的类在导入numpy函数时失去了对它的访问权,而在我像在终端中运行脚本一样运行它时却没有

  • 我想我也不明白为什么人们对自己的名称空间如此保护,也就是说,为什么这么多代码示例显示
    将numpy导入为np
    ,并使用所有函数作为
    np.exp(x)
    ,等等,我没有太多的计算机科学背景,所以我可以从你提供的任何解释中受益匪浅-文档对我来说有点神秘

  • Python版本:2.7.8 | Anaconda 2.1.0(x86_64)|(默认,2014年8月21日,15:21:46) [GCC 4.2.1(Apple Inc.build 5577)]
    在Mac OSX 10.6.8上,当您在IPython中调用
    %run WC_class.py
    时,您所做的是将源文件的内容直接加载到交互式命名空间中。因为您已经在IPython会话中从numpy import*
    调用了
    exp
    在当前“模块”(在本例中,它只是IPython交互名称空间)的全局变量集中被定义为
    numpy.exp
    ,所以当您在
    WC\U unit.update()中调用
    (或
    WC_class.py
    中的任何其他地方)它都可以正常工作

    但是,您没有在
    test.py
    的顶部执行
    from numpy import*
    ,因此当您将
    WC\u单元
    导入脚本时,当前模块(现在是
    test
    脚本)的范围内没有定义
    exp

    您已经在
    WC\u unit.update()
    方法本身中尝试了从numpy import*
    导入
    ,但这将失败,因为(事实上,您在尝试导入
    WC\u unit
    !)时应该看到一个
    SyntaxWarning
    ),因为导入失败,
    exp
    仍然未定义,并且
    WC\u unit.update()
    方法将引发您看到的
    名称错误

    您应该做的是在使用numpy函数的任何源文件的顶部有一个导入行:

    import numpy as np
    
    然后通过
    np.
    名称空间引用任何numpy函数


    关于你的第三点,主要原因是

    import numpy as np
    
    x = np.exp(y) # etc.
    
    而不是

    from numpy import *
    
    x = exp(y)   # etc.
    
    后一种方法污染了全局名称空间

    假设您已经定义了自己的函数
    exp
    。当您从numpy import*
    执行
    操作时,您将使用
    numpy.exp
    覆盖自己的函数
    exp
    ,因此当您以后调用
    exp(y)时
    它可能不会达到您期望的效果。例如,这正是某些内置Python函数(如
    sum
    all
    )所发生的情况:

    print(sum.__module__)
    # __builtin__
    
    from numpy import *
    
    print(sum.__module__)
    # numpy.core.fromnumeric
    
    更重要的是,这或多或少是不可逆的-一旦您从模块导入中执行了
    *
    ,就没有简单的方法可以去除您导入到命名空间中的内容(或者通过导入它们上面的内容来恢复任何旧模块或变量)


    只要您将每个模块的所有内容保留在自己单独的名称空间中,就不会有名称空间冲突的风险,也不会对每个函数或类的来源产生歧义。按照惯例,我们使用
    np
    来引用numpy的名称空间,
    plt
    来引用
    matplotlib.pyplot
    等的名称空间。

    停止使用
    fromnumpy import*
    和preference
    import numpy
    并使用
    numpy.array
    numpy.mean
    等。这可以防止名称空间污染,这会造成您所看到的问题。请始终显示问题中任何错误消息的完整回溯谢谢!我不确定这是否确实发生了,但我已经知道了我确实能够更多地了解类和对象的工作方式,并将其分解为更小的部分。在我学习如何写作的过程中,我可能会问一些更具哲学意义的问题,我感谢你的透彻而直截了当的回答。如果有人能将我链接到任何关于如何使用类开发模拟的教程我很想读这些书