Можно ли определить более одной функции для файла в MATLAB и получить к ним доступ вне этого файла?

189

Когда я учился на получение степени бакалавра в EE, MATLAB требовал, чтобы каждая функция определялась в собственном файле, даже если она была однострочным.

Сейчас я учусь в аспирантуре, и мне нужно написать проект в MATLAB. Это все еще требование для более новых версий MATLAB?

Если в файл можно поместить более одной функции, существуют ли какие-либо ограничения на это? Например, могут ли доступны все функции в файле из-за пределов файла или только функция с тем же именем, что и файл?

Примечание. Я использую MATLAB release R2007b.

Теги:
scope
file
function
function-declaration

8 ответов

234
Лучший ответ

Первая функция в m файле (т.е. основная функция) вызывается при вызове этого m файла. Не требуется, чтобы основная функция имела то же имя, что и файл m, но для ясности это должно быть. Когда функция и имя файла различаются, имя файла должно использоваться для вызова основной функции.

Все последующие функции в m файле, называемые локальные функции (или "подфункции" в старой терминологии), могут быть вызваны только основная функция и другие локальные функции в этом m файле. Функции других m файлов не могут вызывать их.

Кроме того, вы также можете объявлять функции в рамках других функций. Они называются вложенными функциями, и их можно вызывать только внутри функции, в которую они вложены. Они также могут иметь доступ к переменным в функциях, в которых они вложены, что делает их весьма полезными, хотя и немного сложными для работы.

Больше пищи для размышлений...

Существуют способы обхода описанного выше нормального режима работы функции, такие как передача функций handles в качестве выходных аргументов, как указано в Ответ Jonas. Тем не менее, я бы не стал предлагать привычку прибегать к таким трюкам, так как есть, вероятно, гораздо лучшие варианты для организации ваших файлов.

Например, предположим, что у вас есть основная функция A в m файле A.m, а также локальные функции D, E и F. Теперь предположим, что у вас есть две другие связанные функции B и C в m файлах B.m и C.m, соответственно, что вы также хотите иметь возможность звонить D, E и F. Вот некоторые варианты, которые у вас есть:

  • Поместите D, E и F каждый в свои собственные m файлы, позволяя любой другой функции их вызывать. Недостатком является то, что объем этих функций большой и не ограничивается только A, B и C, но вверху является то, что это довольно просто.

  • Создайте defineMyFunctions m файл (например, в примере Джонаса) с D, E и F как локальные функции и главную функцию, которая просто возвращает к ним дескрипторы функций. Это позволяет хранить D, E и F в одном файле, но ничего не делает в отношении объема этих функций, поскольку любая функция, которая может вызывать defineMyFunctions, может вызывать их. Вы также должны беспокоиться о передаче функций в качестве аргументов, чтобы убедиться, что они есть там, где они вам нужны.

  • Скопируйте D, E и F в B.m и C.m в качестве локальных функций. Это ограничивает объем их использования только A, B и C, но делает обновление и обслуживание вашего кошмара кошмаром, потому что у вас есть три копии одного и того же кода в разных местах.

  • Используйте частные функции! Если у вас есть A, B и C в том же каталоге, вы можете создать подкаталог под названием private и поместить D, E и F туда, каждый в виде отдельного m файла. Это ограничивает их область действия, поэтому их можно вызывать только из функций в каталоге непосредственно выше (т.е. A, B и C) и удерживать их вместе в одном и том же месте (но все еще разные m файлы):

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

Все это выходит за рамки вашего вопроса и, вероятно, более подробно, чем вам нужно, но я подумал, что было бы полезно затронуть более общую проблему организации всех ваших m файлов.;)

  • 0
    Отличный! Один из тех ответов, из-за которого я бы хотел, чтобы у SO была опция «любимый ответ»!
  • 3
    Любимый вариант ответа выглядит так ^ , @idigas
Показать ещё 1 комментарий
63

Как правило, ответ на ваш вопрос - нет, вы не можете определить более чем одну внешнюю видимую функцию для каждого файла. Однако вы можете возвращать дескрипторы функций для локальных функций, и удобный способ сделать это - сделать их полями структуры. Вот пример:

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
34

Единственный способ иметь несколько, отдельно доступных функций в одном файле - это определить СТАТИЧЕСКИЕ МЕТОДЫ, используя объектно-ориентированное программирование. Вы должны получить доступ к функции как myClass.static1(), myClass.static2() и т.д.

Функциональность OOP официально поддерживается только с R2008a, поэтому, если вы не хотите использовать старый, недокументированный синтаксис ООП, ответ для вас - нет, как объясняется @gnovice.

EDIT

Еще один способ определить несколько функций внутри файла, которые доступны извне, - это создать функцию, которая возвращает несколько функций . Другими словами, вы бы назвали вашу определяющую функцию [fun1,fun2,fun3]=defineMyFunctions, после которой вы могли бы использовать out1=fun1(inputs) и т.д.

  • 0
    Я бы не использовал oop для этой цели, это добавляет существенные издержки, особенно для статических методов. ( stackoverflow.com/questions/1693429/… )
  • 1
    @Daniel: накладные расходы заметны только в том случае, если вы выполняете огромное количество вызовов функций и вычисления в методе являются квази-мгновенными. Оба условия часто указывают на плохой дизайн - отсутствие векторизации и бессмысленные функции. Таким образом, я не был бы слишком обеспокоен.
17

Мне очень нравится ответ SCFrench. Я хотел бы указать, что его можно легко изменить, чтобы импортировать функции напрямую в рабочую область с помощью функции assignin. (Выполнение этого, как это напоминает мне много 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

И затем используется таким образом:

>> makefuns
ans =
Done importing functions to workspace

>> fun1(123)
ans =
   123

>> fun2()
ans =
     1
7

В том же ключе, что и SCFrench, но с более стильным стилем С#..

Я бы (и часто делал) создавал класс, содержащий несколько статических методов. Например:

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);     
4

Я определяю несколько функций в одном файле .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'.
  • 1
    Нет, в Matlab нет команды source :(
3

Вы также можете группировать функции в один основной файл вместе с основной функцией, выглядящей так:

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

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

Тогда вызов subfun1 будет выглядеть так: ул = основная ( 'subfun1')

0

Как и в случае R2017b, это официально невозможно. соответствующая документация гласит, что:

Файлы программы могут содержать несколько функций. Если файл содержит только определения функций, первая функция является основной функцией и является функцией, которую MATLAB связывает с именем файла. Функции, которые следуют за основной функцией или кодом script, называются локальными функциями. Локальные функции доступны только в файле.

Однако обходные пути, предложенные в других ответах, могут достичь чего-то подобного.

  • 0
    Это не совсем то, что сказал Гновице в начале своего ответа?
  • 0
    @Adiel Возможно, но с тех пор прошло несколько лет, и кто-то может задаться вопросом, изменилось ли что-нибудь.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню