227 votes

Est-il possible de définir plus d'une fonction par fichier dans MATLAB, et d'y accéder depuis l'extérieur de ce fichier ?

Lorsque j'étudiais pour mon diplôme de premier cycle en EE, MATLAB exigeait que chaque fonction soit définie dans son propre fichier, même s'il s'agissait d'une simple ligne.

Je suis actuellement en train de préparer un diplôme d'études supérieures et je dois rédiger un projet en MATLAB. Est-ce encore une exigence pour les nouvelles versions de MATLAB ?

S'il est possible de mettre plus d'une fonction dans un fichier, y a-t-il des restrictions à cela ? Par exemple, peut-on accéder à toutes les fonctions du fichier depuis l'extérieur de celui-ci, ou seulement à la fonction qui porte le même nom que le fichier ?

Remarque : j'utilise la version R2007b de MATLAB.

279voto

gnovice Points 70970

La première fonction d'un fichier m (c'est-à-dire le fichier fonction principale ), est invoqué lorsque ce m-file est appelé. Il n'est pas requis que la fonction principale ait le même nom que le fichier m, mais pour plus de clarté, il devrait . Lorsque la fonction et le nom du fichier diffèrent, le nom du fichier doit être utilisé pour appeler la fonction principale.

Toutes les fonctions suivantes du fichier m, appelées fonctions locales (ou "sous-fonctions" dans l'ancienne terminologie), ne peuvent être appelées que par la fonction principale et les autres fonctions locales de ce m-file. Les fonctions d'autres fichiers m ne peuvent pas les appeler. À partir de R2016b, vous pouvez ajouter des fonctions locales aux scripts également, bien que le comportement de scoping soit toujours le même (c'est-à-dire qu'ils ne peuvent être appelés que depuis l'intérieur du script).

En outre, vous pouvez également déclarer des fonctions sur d'autres fonctions. Ces fonctions sont appelées fonctions imbriquées et celles-ci ne peuvent être appelées qu'à l'intérieur de la fonction dans laquelle elles sont imbriquées. Elles peuvent également avoir accès aux variables des fonctions dans lesquelles elles sont imbriquées, ce qui les rend très utiles, même si leur utilisation est un peu délicate.

Plus d'éléments de réflexion...

Il existe quelques moyens de contourner le comportement normal de délimitation de la fonction décrit ci-dessus, comme le passage de poignées de fonction comme arguments de sortie, comme mentionné dans les réponses de SCFrench y Jonas (ce qui, à partir de R2013b, est facilité par l'option localfunctions fonction). Cependant, je ne suggérerais pas de prendre l'habitude de recourir à de telles astuces, car il existe probablement de bien meilleures options pour organiser vos fonctions et vos fichiers.

Par exemple, disons que vous avez une fonction principale A dans un fichier m A.m ainsi que les fonctions locales D , E y F . Maintenant, disons que vous avez deux autres fonctions connexes B y C dans les m-files B.m y C.m respectivement, que vous voulez également pouvoir appeler D , E y F . Voici quelques options qui s'offrent à vous :

  • Mettez D , E y F chacun dans leurs propres fichiers m séparés, permettant à toute autre fonction de les appeler. L'inconvénient est que le champ d'application de ces fonctions est large et ne se limite pas seulement à A , B y C mais l'avantage est que c'est assez simple.

  • Créer un defineMyFunctions m-file (comme dans l'exemple de Jonas) avec D , E y F en tant que fonctions locales et une fonction principale qui leur renvoie simplement des handles de fonctions. Cela vous permet de conserver D , E y F dans le même fichier, mais cela ne fait rien concernant la portée de ces fonctions puisque toute fonction qui peut appeler defineMyFunctions peut les invoquer. Vous devez également vous préoccuper de faire passer les gestionnaires de fonctions en tant qu'arguments pour être sûr de les avoir là où vous en avez besoin.

  • Copie D , E y F en B.m y C.m comme des fonctions locales. Cela limite la portée de leur utilisation à A , B y C Mais la mise à jour et la maintenance de votre code sont un cauchemar car vous avez trois copies du même code à différents endroits.

  • Utilisez fonctions privées ! Si vous avez A , B y C dans le même répertoire, vous pouvez créer un sous-répertoire appelé private et place D , E y F là-dedans, chacun comme un fichier m séparé. Cela limite leur portée de sorte qu'elles ne peuvent être appelées que par des fonctions situées dans le répertoire immédiatement supérieur (c'est-à-dire A , B y C ) et les garde ensemble au même endroit (mais toujours avec des m-files différents) :

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

Tout ceci sort un peu du cadre de votre question, et est probablement plus détaillé que ce dont vous avez besoin, mais j'ai pensé qu'il serait bon d'aborder le problème plus général de l'organisation de tous vos fichiers m. ;)

3 votes

L'option de réponse favorite ressemble à ceci ^ , @idigas

1 votes

@embert Je suppose qu'il voulait dire qu'il s'agit de favoriser une question, qui peut être votée par le haut indépendamment de la favorisation.

84voto

SCFrench Points 4826

En général, la réponse à votre question est non, vous ne pouvez pas définir plus d'une fonction visible de l'extérieur par fichier. Vous pouvez cependant renvoyer les identifiants des fonctions locales, et une façon pratique de le faire est de les transformer en champs d'une structure. Voici un exemple :

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

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

function z=fun2
  z=1;
end

Et voici comment il pourrait être utilisé :

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

38voto

Jonas Points 54073

La seule façon d'avoir plusieurs fonctions accessibles séparément dans un seul fichier est de définir MÉTHODES STATIQUES en utilisant la programmation orientée objet . Vous accédez à la fonction comme myClass.static1() , myClass.static2() etc.

La fonctionnalité OOP n'est officiellement prise en charge que depuis la R2008a, donc à moins que vous ne souhaitiez utiliser l'ancienne syntaxe OOP non documentée, la réponse pour vous est non, comme l'explique @gnovice .

EDIT

Une autre façon de définir des fonctions multiples à l'intérieur d'un fichier qui sont accessibles de l'extérieur est de créer une fonction qui renvoie de multiples poignées de fonction . En d'autres termes, vous appelleriez votre fonction de définition comme suit [fun1,fun2,fun3]=defineMyFunctions après quoi vous pouvez utiliser out1=fun1(inputs) etc.

0 votes

Je n'utiliserais pas oop dans ce but, il ajoute une surcharge substantielle, surtout pour les méthodes statiques. ( stackoverflow.com/questions/1693429/ )

1 votes

@Daniel : L'overhead n'est perceptible que si vous faites une énorme quantité d'appels de fonction et que les calculs dans la méthode sont quasi-instantanés. Ces deux conditions indiquent souvent une mauvaise conception - pas de vectorisation, et des fonctions sans signification. Ainsi, je ne serais pas trop inquiet.

24voto

Ru Hasha Points 91

J'aime beaucoup la réponse de SCFrench - je voudrais signaler qu'elle peut facilement être modifiée pour importer les fonctions directement à l'espace de travail en utilisant la fonction assignin. (Cette façon de faire me rappelle beaucoup la façon de faire de Python "import x from 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

Et ensuite utilisé de cette façon :

>> makefuns
ans =
Done importing functions to workspace

>> fun1(123)
ans =
   123

>> fun2()
ans =
     1

1 votes

assignin('caller',...) serait plus correct. Vous pourriez vouloir utiliser ces fonctions à l'intérieur d'une autre fonction.

12voto

SmallJoeMan Points 68

Dans la même veine que la réponse de SCFrench, mais avec une tournure plus C#

Je ferais (et je fais souvent) une classe contenant plusieurs méthodes statiques. Par exemple :

classdef Statistics

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

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

end

Comme les méthodes sont statiques, il n'est pas nécessaire d'instancier la classe. Vous appelez les fonctions comme suit :

data = 1:10;

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X