MATLAB'da dosya başına birden fazla işlev tanımlamak ve bunlara bu dosyanın dışından erişmek mümkün müdür?


217

EE'deki lisans eğitimimi okurken MATLAB, tek bir işlev olsa bile her işlevin kendi dosyasında tanımlanmasını gerektiriyordu.

Şimdi yüksek lisans eğitimi alıyorum ve MATLAB'da bir proje yazmam gerekiyor. Bu hala MATLAB'ın daha yeni sürümleri için bir gereklilik mi?

Bir dosyaya birden fazla işlev koymak mümkünse, bununla ilgili herhangi bir kısıtlama var mı? Örneğin, dosyadaki tüm işlevlere dosyanın dışından mı, yoksa yalnızca dosyayla aynı ada sahip olan işleve mi erişilebilir?

Not: MATLAB R2007b sürümünü kullanıyorum.

Yanıtlar:


271

Bir m dosyasındaki ilk işlev (yani ana işlev ), o m dosyası çağrıldığında çağrılır. O değil gerekli ana işlevi m-dosyayla aynı ada sahip olduğunu, ancak netlik için o olmalıdır . İşlev ve dosya adı farklı olduğunda, ana işlevi çağırmak için dosya adı kullanılmalıdır.

M dosyasındaki yerel işlevler (veya eski terminolojideki "alt işlevler ") olarak adlandırılan tüm sonraki işlevler yalnızca ana işlev ve o m dosyasındaki diğer yerel işlevler tarafından çağrılabilir. Diğer m dosyalarındaki işlevler onları çağıramaz. Kapsam belirleme davranışı hala aynı olmasına rağmen, R2016b'den başlayarak, komut dosyalarına yerel işlevler de ekleyebilirsiniz (örn. Yalnızca komut dosyasından çağrılabilirler).

Ayrıca, diğer işlevler içindeki işlevleri de bildirebilirsiniz . Bunlara iç içe işlevler denir ve bunlara yalnızca iç içe oldukları işlevden çağrılabilir. İç içe yerleştirildikleri işlevlerdeki değişkenlere de erişebilirler, bu da çalışmak için biraz zor olsa da onları oldukça yararlı kılar.

Düşünce için daha fazla yiyecek ...

Normal fonksiyon kapsam belirleme davranışının etrafında, SCFrench ve Jonas'ın cevaplarında belirtildiği gibi çıkış argümanları olarak fonksiyon tutamaçlarını iletme gibi bazı yollar vardır (R2013b'den başlayarak,localfunctions fonksiyon ) . Ancak, işlevlerinizi ve dosyalarınızı düzenlemek için muhtemelen çok daha iyi seçenekler olduğu için, bu tür hilelere başvurmayı alışkanlık haline getirmeyi önermem.

Örneğin, bir ana işlevi var diyelim Abir m-dosyada A.myerel fonksiyonları ile birlikte D, Eve F. Şimdi iki diğer ilgili işlevleri olduğunu varsayalım Bve Cm-dosyaları B.mve C.mayrıca arama yapabilmek istediğiniz, sırasıyla D, Eve F. İşte sahip olduğunuz bazı seçenekler:

  • , Ve her birini kendi ayrı m dosyalarına koyun D, diğer işlevlerin onları çağırmasına izin verin. Olumsuz bu fonksiyonların kapsamı geniştir ve sadece sınırlı olmamasıdır , ve , ama ters bu oldukça basit olmasıdır.EFABC

  • Bir oluşturma defineMyFunctionsile (Jonas'ın örnekte olduğu gibi) m-dosyası D, Eve Fyerel fonksiyonları ve bir ana fonksiyonu olarak o basitçe döner onlara kolları çalışır. Bu saklamanızı sağlar D, Eve Faynı dosyada, ancak çağırabilir herhangi fonksiyonu beri bu fonksiyonların kapsamına ilişkin bir şey yapmaz defineMyFunctionsbunları çağırabilir. Ayrıca, ihtiyacınız olan yere sahip olduğunuzdan emin olmak için işlev tutamaçlarını argümanlar olarak iletme konusunda endişelenmeniz gerekir.

  • Kopya D, Eve Fiçine B.mve C.myerel işlevler gibi. Bu, kullanımlarının kapsamını sadece A, Bve ile sınırlandırır C, ancak farklı yerlerde aynı kodun üç kopyasına sahip olduğunuz için kodunuzun güncellenmesini ve bakımını kabus yapar.

  • Özel işlevleri kullanın ! Eğer varsa A, Bve Caynı dizinde, bir adlandırılan alt dizin oluşturabilir privateve yeri D, Eve Forada ayrı bir m-dosya olarak her. Bu sadece hemen yukarıdaki dizinde fonksiyonları tarafından çağrılan (yani böylece onların kapsamını sınırlar A, Bve C) ve aynı yerde biraraya tutar (ama yine de farklı m-dosyaları):

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

Bütün bunlar sorunuzun kapsamı dışında kalıyor ve muhtemelen ihtiyacınız olandan daha ayrıntılı, ancak tüm m dosyalarınızı düzenlemenin daha genel endişesine değinmenin iyi olabileceğini düşündüm. ;)


3
Favori cevap seçeneği şöyle görünüyor ^, @idigas
embert

1
@embert Bir sorudan hoşlanma çizgisi boyunca demek istediğini varsayıyorum, bu da hoşnutsuzluktan bağımsız olarak oylanabilir.
OJFord

79

Genel olarak, sorunuzun yanıtı hayırdır, dosya başına birden fazla harici olarak görünen işlev tanımlayamazsınız. Bununla birlikte, işlev tutamaçlarını yerel işlevlere döndürebilirsiniz ve bunu yapmanın uygun bir yolu, onları bir yapı alanı yapmaktır. İşte bir örnek:

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

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

function z=fun2
  z=1;
end

Ve işte nasıl kullanılabilir:

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

36

Tek bir dosyada birden fazla, ayrı olarak erişilebilir fonksiyona sahip olmanın tek yolu, nesne yönelimli programlama kullanarak STATİK YÖNTEMLER tanımlamaktır . Sen işleve erişmek istiyorum , vbmyClass.static1()myClass.static2()

OOP işlevselliği yalnızca R2008a'dan beri resmi olarak desteklenmektedir, bu nedenle eski, belgesiz OOP sözdizimini kullanmak istemiyorsanız, @gnovice tarafından açıklandığı gibi sizin için cevap hayır .

DÜZENLE

Bir dosyanın içinde dışarıdan erişilebilen birden çok işlevi tanımlamanın bir başka yolu, birden çok işlev tutamağı döndüren bir işlev oluşturmaktır . Başka bir deyişle, tanımlayıcı işlevinizi [fun1,fun2,fun3]=defineMyFunctions, daha sonra kullanabileceğiniz out1=fun1(inputs)gibi çağırırsınız .


Bu amaçla oop kullanmazdım, özellikle statik yöntemler için önemli bir ek yük ekler. ( stackoverflow.com/questions/1693429/… )
Daniel

1
@Daniel: Tepegöz ancak çok fazla işlev çağrısı yaparsanız ve yöntemdeki hesaplamalar yarı anlıksa fark edilir. Her iki koşul da genellikle kötü tasarıma işaret eder - vektörizasyon ve anlamsız işlevler yoktur. Böylece, çok endişelenmezdim.
Jonas

23

SCFrench'in cevabını gerçekten seviyorum - atama işlevini kullanarak fonksiyonları doğrudan çalışma alanına almak için kolayca değiştirilebileceğini belirtmek isterim . (Böyle yapmak bana bir sürü Python'un "x'i y'den içe aktarma" şeklini hatırlatıyor)

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

Ve sonra bu şekilde kullanılır:

>> makefuns
ans =
Done importing functions to workspace

>> fun1(123)
ans =
   123

>> fun2()
ans =
     1

assignin('caller',...)daha doğru olur. Bu işlevleri başka bir işlev içinden kullanmak isteyebilirsiniz.
Cris Luengo

10

SCFrench'in cevabı ile aynı satırlar boyunca, ancak daha C # tarzı bir dönüşle ..

Birden fazla statik yöntem içeren bir sınıf yapmak (ve genellikle yapmak). Örneğin:

classdef Statistics

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

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

end

Yöntemler statik olduğu için sınıfı saptamanıza gerek yoktur. İşlevleri şu şekilde çağırırsınız:

data = 1:10;

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

4

Octave ile bir .m dosyasında birden çok işlevi tanımlar ve sonra bu dosyadaki işlevleri kullanmak için gereken .m dosyasındaki komutu kullanın:

source("mycode.m");

Matlab'da mevcut olup olmadığından emin değilim.

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'.

3

Ayrıca, işlevleri ana işlevle birlikte aşağıdaki gibi görünen bir ana dosyada gruplayabilirsiniz:

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

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

Sonra subfun1 çağrısı şöyle görünecektir: str = main ('subfun1')


0

R2017b'den itibaren bu resmi olarak mümkün değildir. İlgili belgeler bildiren:

Program dosyaları birden fazla işlev içerebilir. Dosya yalnızca işlev tanımları içeriyorsa, ilk işlev ana işlevdir ve MATLAB'ın dosya adıyla ilişkilendirdiği işlevdir. Ana işlevi veya kod kodunu izleyen işlevlere yerel işlevler denir. Yerel işlevler yalnızca dosya içinde kullanılabilir.

Ancak, diğer yanıtlarda önerilen geçici çözümler benzer bir şey başarabilir.


Gnovice'nin cevabının başında tam olarak söylediği bu değil mi?
Adiel

@Adiel Belki, ama bu cevaptan bu yana birkaç yıl geçmişti ve birisi bir şeyin değişip değişmediğini merak edebilir.
Dev-iL

Bir şey değişirse hala alamadım ...? :)
Adiel

Hayır! Bu konuyu ele almak için eklenen bazı belgeler dışında.
Dev-iL

Bu yanıtı yazmamın nedeni, birkaç sürüm önce komut dosyalarının sonuna ekleyebileceğiniz işlevler sunmasıydı - bu nedenle bu konuda bir şeylerin değişip değişmediğini merak edebilir (cevap: hayır).
Dev-iL

-1

Birlikte deneyin SCFRench ile Ru Hasha oktav üstünde.

Ve nihayet işe yarıyor: ama bazı değişiklikler yaptım

function message = makefuns
    assignin('base','fun1', @fun1);   % Ru Hasha
    assignin('base', 'fun2', @fun2);  % Ru Hasha
    message.fun1=@fun1;               % SCFrench
    message.fun2=@fun2;               % SCFrench
end

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

function z=fun2
    z=1;
end

Diğer 'm' dosyasında çağrılabilir:

printf("%d\n", makefuns.fun1(123));
printf("%d\n", makefuns.fun2());

Güncelleme:

Bir cevap ekledim, çünkü ne +72 ne de +20 oktavda benim için çalıştı . Yazdığım biri mükemmel çalışıyor (ve daha sonra yazıyı yazdığımda geçen Cuma test ettim).


2
Bunun kopyaladığınız mevcut iki cevaptan nasıl farklı olduğunu açıklayabilirseniz, aşağı oyumu kaldıracağım. Daha önce yorum yapmadığınız için üzgünüm. Her iki yöntemi de tek bir işlevde birleştirmeniz ve bu nedenle gereksiz bir şey yapmanız dışında bunun nasıl farklı olduğunu görmüyorum. Ayrıca, atıfta bulunduğunuz cevaplara uygun bağlantılar ekleyin, "+72" ve "+20" oldukça şifreli, zaman içinde değişecek ve referanslarınızı yapacak olan oy sayılarına atıfta bulunduğunuzu fark etmem biraz zaman aldı. anlaşılmaz.
Cris Luengo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.