web-dev-qa-db-ja.com

MATLABでファイルごとに複数の関数を定義し、そのファイルの外部からそれらにアクセスすることは可能ですか?

EEで学士号を取得するために勉強していたとき、MATLABでは、1行であっても各関数を独自のファイルで定義する必要がありました。

現在、大学院の学位を取得しているため、MATLABでプロジェクトを作成する必要があります。これは、MATLABの新しいバージョンの要件ですか?

1つのファイルに複数の関数を配置できる場合、これに制限はありますか?たとえば、ファイル内のすべての関数にファイルの外部からアクセスできますか、それともファイルと同じ名前の関数のみにアクセスできますか?

注:MATLABリリースR2007bを使用しています。

203
Nathan Fellman

M-ファイルの最初の関数(つまり メイン関数 )は、そのm-ファイルが呼び出されたときに呼び出されます。メイン関数がm-ファイルと同じ名前を持つことはrequiredではありませんが、わかりやすくするためにshouldです。関数とファイル名が異なる場合、ファイル名を使用してメイン関数を呼び出す必要があります。

ローカル関数 (または古い用語では「サブ関数」)と呼ばれるmファイル内の後続の関数はすべて、そのmファイル内のメイン関数と他のローカル関数によってのみ呼び出すことができます。他のmファイル内の関数はそれらを呼び出すことができません。 R2016b以降では、 ローカル関数をスクリプトに追加 を使用できますが、スコープの動作は同じです(つまり、スクリプト内からのみ呼び出すことができます)。

さらに、他の関数内で関数を宣言することもできます。これらは ネストされた関数 と呼ばれ、ネストされた関数内からのみ呼び出すことができます。また、入れ子になっている関数内の変数にアクセスすることもできるため、操作が少し難しくなりますが非常に便利です。

思考のためのより多くの食物...

SCFrench および Jonas からの回答に記載されているように、出力引数として function handles を渡すなど、上記の通常の関数スコーピング動作を回避する方法がいくつかあります。 =(R2013b以降、 localfunctions 関数によって促進されます)。ただし、関数やファイルを整理するためのはるかに優れたオプションがある可能性があるため、このようなトリックに頼る習慣にすることはお勧めしません。

たとえば、ローカル関数AD、およびEとともに、mファイルA.mにメイン関数Fがあるとします。ここで、mファイルB.mC.mにそれぞれ2つの関連する関数BCがあり、DE、およびFを呼び出すこともできます。いくつかのオプションがあります:

  • DE、およびFをそれぞれ別のmファイルに入れて、他の関数がそれらを呼び出すことができるようにします。欠点は、これらの関数のスコープが大きく、AB、およびCだけに限定されないことですが、長所はこれが非常に単純であることです。

  • defineMyFunctionsD、およびEをローカル関数として使用し、関数ハンドルを単に返すメイン関数を使用して、F mファイル(Jonasの例のように)を作成します。これにより、DE、およびFを同じファイルに保持できますが、defineMyFunctionsを呼び出すことができるすべての関数がそれらを呼び出すことができるため、これらの関数のスコープに関しては何もしません。また、関数ハンドルを引数として渡すことを心配して、必要な場所に関数ハンドルがあることを確認する必要があります。

  • DE、およびFB.mおよびC.mにローカル関数としてコピーします。これにより、使用範囲がAB、およびCに限定されますが、異なる場所に同じコードのコピーが3つあるため、コードの更新と保守が悪夢になります。

  • プライベート関数を使用します同じディレクトリにAB、およびCがある場合、privateというサブディレクトリを作成できますそして、DE、およびFをそれぞれ個別のmファイルとして配置します。これにより、スコープが制限されるため、すぐ上のディレクトリ(AB、およびC)の関数によってのみ呼び出され、同じ場所(ただし、異なるmファイル)にまとめられます。

    myDirectory/
        A.m
        B.m
        C.m
        private/
            D.m
            E.m
            F.m
    

これはすべてあなたの質問の範囲外であり、おそらくあなたが必要とするよりも詳細ですが、すべてのmファイルを整理するというより一般的な懸念に触れるのが良いと思いました。 ;)

263
gnovice

一般的に、あなたの質問に対する答えは「いいえ」です。ファイルごとに複数の外部から見える関数を定義することはできません。ただし、ローカル関数に関数ハンドルを返すことはできますが、そのための便利な方法は、それらを構造体のフィールドにすることです。以下に例を示します。

function funs = makefuns
  funs.fun1=@fun1;
  funs.fun2=@fun2;
end

function y=fun1(x)
  y=x;
end

function z=fun2
  z=1;
end

そして、それがどのように使用される可能性があります:

>> myfuns = makefuns;
>> myfuns.fun1(5)    
ans =
     5
>> myfuns.fun2()     
ans =
     1
76
SCFrench

単一のファイルに複数の個別にアクセス可能な関数を持つ唯一の方法は、 オブジェクト指向プログラミング を使用して STATIC METHODS を定義することです。 myClass.static1()myClass.static2()などとして関数にアクセスします。

OOP機能はR2008aから公式にサポートされているだけです。したがって、ドキュメント化されていない古いOOP構文を使用する場合を除き、 @ gnovice で説明するように答えはありません。

編集

外部からアクセス可能な複数の関数をファイル内で定義するもう1つの方法は、複数の 関数ハンドル を返す関数を作成することです。つまり、定義関数を[fun1,fun2,fun3]=defineMyFunctionsとして呼び出し、その後でout1=fun1(inputs)などを使用できます。

36
Jonas

私はSCFrenchの答えが本当に好きです-assignin関数を使用してワークスペースに関数直接をインポートするように簡単に変更できることを指摘したいと思います。 (このようにすることで、Pythonの「xからyをインポートする」方法を思い起こさせる)

function message = makefuns
  assignin('base','fun1',@fun1);
  assignin('base','fun2',@fun2);
  message='Done importing functions to workspace';
end

function y=fun1(x)
  y=x;
end

function z=fun2
  z=1;
end

そして、このように使用されます:

>> makefuns
ans =
Done importing functions to workspace

>> fun1(123)
ans =
   123

>> fun2()
ans =
     1
23
Ru Hasha

SCFrenchの答えと同じ行に沿って、ただしC#スタイルのスピンを追加します。

複数の静的メソッドを含むクラスを作成します(そして頻繁に作成します)。例えば:

classdef Statistics

    methods(Static)
        function val = MyMean(data)
            val = mean(data);
        end

        function val = MyStd(data)
            val = std(data);
        end
    end

end

メソッドは静的なので、クラスをインスタンス化する必要はありません。次のように関数を呼び出します。

data = 1:10;

mean = Statistics.MyMean(data);
std = Statistics.MyStd(data);     
9
SmallJoeMan

Octaveを使用して1つの.mファイルに複数の関数を定義し、そのファイルの関数を使用する必要がある.mファイル内からコマンドを使用します。

source("mycode.m");

これがMatlabで利用可能かどうかわかりません。

octave:8> help source
'source' is a built-in function

 -- Built-in Function:  source (FILE)
     Parse and execute the contents of FILE.  This is equivalent to
     executing commands from a script file, but without requiring the
     file to be named `FILE.m'.
4
J.D.

次のようなメイン関数とともに、1つのメインファイル内の関数をグループ化することもできます。

function [varargout] = main( subfun, varargin )
[varargout{1:nargout}] = feval( subfun, varargin{:} ); 

% paste your subfunctions below ....
function str=subfun1
str='hello'

次にsubfun1を呼び出すと、次のようになります。str = main( 'subfun1')

3
Thierry Dalon

R2017bの時点では、これは公式には不可能です。 関連ドキュメント は次のように述べています:

プログラムファイルには複数の機能を含めることができます。ファイルに関数定義のみが含まれる場合、最初の関数はメイン関数であり、MATLABがファイル名に関連付ける関数です。メイン関数またはスクリプトコードに続く関数は、ローカル関数と呼ばれます。ローカル関数はファイル内でのみ使用可能です。

ただし、他の回答で提案されている回避策で同様のことが実現できます。

0
Dev-iL