2011-04-12 63 views
11

我有一個應該放入一個包的輔助函數的目錄。第一步顯然是命名目錄,如+mypackage\,所以我可以用mypackage.somefunction調用函數。問題是,一些函數依賴於另一個函數,顯然MATLAB需要包函數來調用同一個包中的函數,仍然通過明確聲明包名稱,所以我必須重寫所有的函數調用。更糟糕的是,如果我決定重命名包,所有函數調用都必須重寫。當我的cd當它的名字以+開頭時,這些功能甚至不能正確地工作。如何將一個目錄轉換爲一個包?

有沒有比重寫更容易的解決方案? 或至少是一些自我指涉如import this.*,以方便將來的包重命名?


編輯我發現同樣適用於類和靜態方法,這就是爲什麼我把自我指涉的部分爲this separate question

+0

在文件的開頭調用* import *應該完成這項工作。查看文檔[import](http://www.mathworks.de/help/techdoc/ref/import.html)瞭解更多信息。 – zellus 2011-04-12 13:10:43

+0

@zellus:謝謝,我已經嘗試過了 - 我必須在程序包中包含'import mypackage。*'到_every_函數(導入在函數工作區中,而不是全局函數),並且當我決定重命名包:( – 2011-04-12 13:16:41

回答

14

事實上,我不知道你應該經常重新命名你的軟件包。在我看來,package in MATLAB背後的全部想法是將一組相關函數和類組織到一個集合中,您可以輕鬆使用或分發爲「工具箱」,而不必擔心名稱衝突。因此,將函數和類放入包中就像最後的步驟,您可以執行一個很好的拋光工具集合,因此您應該沒有太多理由來重命名包。而且,你只需要在包裝函數調用前加上一個包名即可。

...(停下來想,如果有什麼我要建議的是一個好主意;))...

但是,如果你真的避免必須經過你包和prepend你的函數調用一個新的包名,一種方法是使用函數MFILENAME獲取當前正在運行的包函數的完整文件路徑,解析路徑字符串以查找父包目錄(以「+」 「),然後將結果傳遞給IMPORT函數以導入父包。你甚至可以將這些步驟,在一個單獨的功能packagename(要求您同時使用的功能EVALIN):

function name = packagename 
    callerPath = evalin('caller','mfilename(''fullpath'')'); %# Get full path of 
                  %# calling function 
    name = regexp(callerPath,'\+(\w)+','tokens'); %# Parse the path string to get 
               %# package directories 
    name = strcat([name{:}],...       %# Format the output 
       [repmat({'.'},1,numel(name)-1) {''}]); 
    name = [name{:}]; 
end 

然後你可以把這個在你的包的功能一開始就自動讓他們包括他們的父母包名稱空間:

import([packagename '.*']); 

這是個好主意嗎?那麼,我不確定計算的影響會是什麼,如果你在做這個你每次調用一個包函數。另外,如果您有嵌套包內包你會得到輸出packagename看起來像這樣:

'mainpack.subpack.subsubpack' 

而且調用IMPORT將只包括直接父包subsubpack。如果您還想包含其他父包,則必須從上面的字符串中順序刪除最後一個包,並導入字符串的其餘部分。

總之,這是不是一個非常乾淨解決方案,但它可能使你的包很容易就能以這種方式重新命名。然而,我仍然認爲最好將創建包視爲創建核心工具集的過程中的最後一步,在這種情況下,重命名應該是不太可能的場景,並且將包名調用爲包名只需要做一次。

+0

謝謝,這是我擔心的最好的答案:-7但也許我在概念上有點問題:如果你在一個目錄中編寫(或接收,更準確)許多功能,你會做什麼和現在想把它變成一個包(或工具箱,會有所作爲嗎?)?或者堅持使用包名,並在每個文件中只使用一個'import'是一個非常好的解決方案? – 2011-04-12 16:01:49

+2

@Tobias:如果我在在這種情況下,我首先要定義一個包名(例如'mypack'),然後咬一口子,然後通過所有代碼來找到包函數互相調用的位置,將'mypack.'添加到正確調用的調用他們的包。通過使用一些依賴工具可以使這一步變得更加容易,這些工具可以告訴你哪些函數調用或被哪些其他函數調用。 [這個SO問題](http://stackoverflow.com/questions/5518200/automatically-generating-a-diagram-of-function-calls-in-matlab)鏈接到一些這樣的選項。 – gnovice 2011-04-12 16:16:08

+0

謝謝,這可能比啓發式地在每個函數中添加'import mypack。*'好得多[ – 2011-04-12 18:21:23

3

我一直在探索同一個問題的答案,我發現將包與私人文件夾結合可以允許大部分或全部代碼無需修改即可使用。

說你有

+mypackage\intfc1.m 
+mypackage\intfc2.m 
+mypackage\private\foo1.m 
+mypackage\private\foo2.m 
+mypackage\private\foo3.m 
然後從 intfc1

foo1foo2foo3都沒有任何包裝預選賽或import語句訪問,並且foo1foo2foo3也可以相互調用,沒有任何包裝限定詞或進口聲明。如果foo1,foo2foo3需要調用intfc1intfc2,則需要限定爲mypackage.intfc1或導入語句。

如果您有大量相互依賴的函數和少量入口點,這可以減少添加限定符或導入語句的負擔。

走得更遠,你可以在封裝級具有相同名稱的私有函數

+mypackage\foo1.m   <--- new interface layer wraps private foo1 
+mypackage\private\foo1.m <--- original function 

其中,例如+mypackage\foo1.m可能創造新的包裝函數:

function answer = foo1(some_parameter) 
    answer = foo1(some_parameter); % calls private function, not itself 
end 

這樣,與上面的intfc1示例不同,所有私有代碼都可以不加修改地運行。特別是在調用任何其他函數時,不需要包限定符,無論它是否在包級別由包裝程序公開。

使用此配置,包括包級別包裝的所有功能都不知道包名稱,因此重命名包只不過是重命名文件夾。

+1

第二個是一個非常有趣的方法,尤其是當你打包來自其他人的代碼並且只想使用幾個函數時。整齊! – 2015-12-18 12:28:56

+0

你會如何將第二種方法應用於課堂? – user1111652 2016-08-19 13:18:36

+0

@Vector'然後從intfc1中,foo1,foo2和foo3都可以訪問,沒有任何包限定符或導入語句'是不是真的。您必須指定包名或導入包。正如前面提到的[這裏](http://stackoverflow.com/a/2748740/2625036):'將一堆函數移動到一個包中的一個主要問題是函數和類不會自動導入它們所在的包。 ' – Ali 2016-12-20 22:23:07

相關問題