2015-02-10 59 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