เป็นไปได้หรือไม่ที่จะกำหนดมากกว่าหนึ่งฟังก์ชั่นต่อไฟล์ใน MATLAB และเข้าถึงได้จากภายนอกไฟล์นั้น?


217

เมื่อฉันเรียนระดับปริญญาตรีของฉันใน EE MATLAB ต้องการให้แต่ละฟังก์ชั่นกำหนดไว้ในไฟล์ของตัวเองแม้ว่ามันจะเป็นแบบเส้นเดียวก็ตาม

ตอนนี้ฉันกำลังเรียนระดับบัณฑิตศึกษาและฉันต้องเขียนโครงการใน MATLAB นี่ยังเป็นข้อกำหนดสำหรับ MATLAB รุ่นใหม่กว่าหรือไม่

หากเป็นไปได้ที่จะวางฟังก์ชั่นมากกว่าหนึ่งไฟล์ไว้ในไฟล์มีข้อ จำกัด ในเรื่องนี้หรือไม่? ตัวอย่างเช่นฟังก์ชั่นทั้งหมดในไฟล์สามารถเข้าถึงได้จากภายนอกไฟล์หรือเฉพาะฟังก์ชั่นที่มีชื่อเดียวกับไฟล์?

หมายเหตุ: ฉันใช้ MATLAB รีลีส R2007b

คำตอบ:


271

ฟังก์ชั่นแรกในไฟล์ m (เช่นฟังก์ชั่นหลัก ) จะถูกเรียกใช้เมื่อเรียกไฟล์ m นั้น มันไม่จำเป็นว่าฟังก์ชั่นหลักที่มีชื่อเดียวกับ M-ไฟล์ แต่เพื่อความชัดเจนก็ควร เมื่อฟังก์ชั่นและชื่อไฟล์ต่างกันต้องใช้ชื่อไฟล์เพื่อเรียกฟังก์ชั่นหลัก

ฟังก์ชั่นที่ตามมาทั้งหมดในไฟล์ m- เรียกว่าฟังก์ชั่นท้องถิ่น (หรือ " ฟังก์ชั่นย่อย" ในคำศัพท์ที่เก่ากว่า) สามารถเรียกได้เฉพาะจากฟังก์ชั่นหลักและฟังก์ชั่นท้องถิ่นอื่น ๆ ในไฟล์ m ฟังก์ชั่นในไฟล์ m อื่น ๆ ไม่สามารถเรียกได้ การเริ่มต้นใน R2016b คุณสามารถเพิ่มฟังก์ชันในเครื่องให้กับสคริปต์ได้เช่นกันแม้ว่าพฤติกรรมการกำหนดขอบเขตยังคงเหมือนเดิม (เช่นสามารถเรียกได้จากภายในสคริปต์เท่านั้น)

นอกจากนี้คุณยังสามารถประกาศฟังก์ชั่นภายในฟังก์ชั่นอื่น ๆ เหล่านี้เรียกว่าฟังก์ชั่นที่ซ้อนกันและเหล่านี้สามารถเรียกได้จากภายในฟังก์ชั่นที่พวกเขาจะซ้อนกัน พวกเขายังสามารถเข้าถึงตัวแปรในฟังก์ชั่นที่ซ้อนกันได้ซึ่งทำให้พวกมันมีประโยชน์แม้ว่าจะใช้งานได้ยากก็ตาม

อาหารมากขึ้นสำหรับความคิด ...

มีวิธีการบางอย่างรอบพฤติกรรมการกำหนดขอบเขตหน้าที่ปกติที่อธิบายไว้ข้างต้นเช่นการส่งผ่านฟังก์ชันจัดการเป็นอาร์กิวเมนต์เอาต์พุตตามที่กล่าวไว้ในคำตอบจากSCFrenchและJonas (ซึ่งเริ่มต้นใน R2013b ช่วยอำนวยความสะดวกโดยlocalfunctionsฟังก์ชัน) อย่างไรก็ตามฉันจะไม่แนะนำให้ใช้นิสัยในการใช้กลอุบายดังกล่าวเนื่องจากมีตัวเลือกที่ดีกว่าสำหรับการจัดระเบียบฟังก์ชั่นและไฟล์ของคุณ

ตัวอย่างเช่นสมมติว่าคุณมีหน้าที่หลักAใน M-ไฟล์A.mพร้อมกับฟังก์ชั่นในท้องถิ่นD, และE Fตอนนี้ขอบอกว่าคุณมีสองฟังก์ชั่นอื่น ๆ ที่เกี่ยวข้องBและCใน m ไฟล์B.mและC.mตามลำดับที่คุณยังต้องการที่จะสามารถที่จะเรียกD, และE Fนี่คือตัวเลือกบางส่วนที่คุณมี:

  • ใส่D, EและFในแต่ละตัวเองแยกต่างหาก M-ไฟล์ของพวกเขาช่วยให้ฟังก์ชั่นอื่น ๆ ที่จะเรียกพวกเขา ข้อเสียคือขอบเขตของฟังก์ชั่นเหล่านี้มีขนาดใหญ่และไม่ได้ จำกัด อยู่เพียงแค่A, BและCแต่กลับหัวกลับหางคือว่านี้จะค่อนข้างง่าย

  • สร้างdefineMyFunctionsM-ไฟล์ (เช่นในตัวอย่างโจนัส) ด้วยD, EและFฟังก์ชั่นในท้องถิ่นและฟังก์ชั่นหลักที่เพียงผลตอบแทนที่ทำงานจับกับพวกเขา นี้จะช่วยให้คุณสามารถเก็บD, EและFในไฟล์เดียวกัน แต่ก็ไม่ได้ทำอะไรเกี่ยวกับขอบเขตของฟังก์ชั่นเหล่านี้ตั้งแต่ฟังก์ชั่นใด ๆ ที่สามารถเรียกใช้defineMyFunctionsสามารถเรียกพวกเขา จากนั้นคุณต้องกังวลเกี่ยวกับการส่งผ่านฟังก์ชั่นการจัดการเป็นอาร์กิวเมนต์เพื่อให้แน่ใจว่าคุณมีพวกเขาในที่ที่คุณต้องการ

  • คัดลอกD, EและFเข้าB.mและC.mฟังก์ชั่นท้องถิ่น ข้อ จำกัด นี้ขอบเขตของการใช้งานของพวกเขาไปเพียงA, BและCแต่ทำให้การปรับปรุงและการบำรุงรักษาของรหัสของคุณฝันร้ายเพราะคุณมีสามชุดของรหัสเดียวกันในสถานที่ที่แตกต่างกัน

  • ใช้ฟังก์ชั่นส่วนตัว ! หากคุณมีA, BและCในไดเรกทอรีเดียวกันคุณสามารถสร้างไดเรกทอรีย่อยที่เรียกว่าprivateและสถานที่D, EและFในนั้นแต่ละแยกมไฟล์ ซึ่งจะ จำกัด ขอบเขตของพวกเขาเพื่อให้พวกเขาเท่านั้นที่สามารถเรียกได้ว่าฟังก์ชั่นในไดเรกทอรีเหนือ (เช่นA, BและC) และช่วยให้พวกเขาร่วมกันในสถานที่เดียวกัน ( แต่ยังคง M-ไฟล์ที่แตกต่างกัน):

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

ทั้งหมดนี้ค่อนข้างจะอยู่นอกขอบเขตของคำถามของคุณและอาจมีรายละเอียดมากกว่าที่คุณต้องการ แต่ฉันคิดว่ามันน่าจะดีที่จะได้สัมผัสกับข้อกังวลทั่วไปของการจัดระเบียบไฟล์ m ทั้งหมดของคุณ ;)


3
ตัวเลือกคำตอบที่ชื่นชอบมีลักษณะเช่นนี้^@idigas
embert

1
@embert ฉันคิดว่าเขาหมายถึงคำถามที่ชื่นชอบซึ่งสามารถโหวตให้เป็นอิสระจากการถูกใจ
OJFord

79

โดยทั่วไปคำตอบสำหรับคำถามของคุณคือไม่คุณไม่สามารถกำหนดฟังก์ชั่นที่มองเห็นภายนอกมากกว่าหนึ่งไฟล์ต่อหนึ่งไฟล์ คุณสามารถคืนค่าการจัดการฟังก์ชั่นไปยังฟังก์ชั่นท้องถิ่นและวิธีที่สะดวกในการทำเช่นนั้นคือการทำให้พวกเขาเขตข้อมูลของ struct นี่คือตัวอย่าง:

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

36

วิธีเดียวที่จะมีหลายฟังก์ชั่นที่สามารถเข้าถึงได้แยกต่างหากในไฟล์เดียวคือการกำหนดSTATIC วิธีการใช้การเขียนโปรแกรมเชิงวัตถุ คุณต้องการเข้าถึงฟังก์ชั่นเป็นmyClass.static1(), myClass.static2()ฯลฯ

ฟังก์ชั่น OOP เป็นเพียงการสนับสนุนอย่างเป็นทางการตั้งแต่ R2008a ดังนั้นถ้าคุณต้องการใช้เก่าไวยากรณ์ OOP ไม่มีเอกสารคำตอบสำหรับคุณคือไม่มีอธิบายโดย@gnovice

แก้ไข

อีกวิธีหนึ่งในการกำหนดหลายฟังก์ชั่นภายในไฟล์ที่สามารถเข้าถึงได้จากภายนอกคือการสร้างฟังก์ชั่นที่ส่งกลับฟังก์ชั่นการจัดการหลาย กล่าวอีกนัยหนึ่งคุณจะเรียกฟังก์ชันการกำหนดของคุณว่า[fun1,fun2,fun3]=defineMyFunctionsหลังจากนั้นคุณสามารถใช้out1=fun1(inputs)ฯลฯ


ฉันจะไม่ใช้ oop เพื่อจุดประสงค์นี้เพิ่มค่าใช้จ่ายที่สำคัญโดยเฉพาะอย่างยิ่งสำหรับวิธีการคงที่ ( stackoverflow.com/questions/1693429/… )
Daniel

1
@Daniel: ค่าใช้จ่ายจะสังเกตได้ก็ต่อเมื่อคุณมีการเรียกใช้ฟังก์ชันจำนวนมากและการคำนวณในวิธีนั้นเสมือนทันที เงื่อนไขทั้งสองมักชี้ไปที่การออกแบบที่ไม่ดี - ไม่มี vectorization และฟังก์ชั่นไร้ความหมาย ดังนั้นฉันจะไม่กังวลเกินไป
Jonas

23

ฉันชอบคำตอบของ SCFrench - ฉันต้องการชี้ให้เห็นว่าสามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อนำเข้าฟังก์ชั่นโดยตรงไปยังพื้นที่ทำงานโดยใช้ฟังก์ชั่น assignin (การทำเช่นนี้ทำให้ฉันนึกถึงวิธีการนำเข้า x จาก y ของ Python ในการทำสิ่งต่าง ๆ )

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

assignin('caller',...)จะถูกต้องมากขึ้น คุณอาจต้องการใช้ฟังก์ชันเหล่านี้จากภายในฟังก์ชันอื่น
Cris Luengo

10

ตามบรรทัดเดียวกันกับคำตอบของ 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);     

4

ฉันกำหนดหลายฟังก์ชั่นในไฟล์. m หนึ่งไฟล์ด้วย Octave จากนั้นใช้คำสั่งจากภายในไฟล์. 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'.

3

คุณสามารถจัดกลุ่มฟังก์ชั่นในไฟล์หลักหนึ่งไฟล์พร้อมกับฟังก์ชั่นหลักที่มีลักษณะดังนี้:

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

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

จากนั้นเรียกsubfun1จะมีลักษณะเช่นนี้: str = main ('subfun1')


0

ในฐานะของ R2017b นี้เป็นไปไม่ได้อย่างเป็นทางการ เอกสารที่เกี่ยวข้องระบุว่า:

ไฟล์โปรแกรมสามารถมีฟังก์ชั่นได้หลายอย่าง หากไฟล์มีเพียงนิยามฟังก์ชันเท่านั้นฟังก์ชันแรกคือฟังก์ชันหลักและเป็นฟังก์ชันที่ MATLAB เชื่อมโยงกับชื่อไฟล์ ฟังก์ชั่นที่ตามฟังก์ชั่นหลักหรือรหัสสคริปต์เรียกว่าฟังก์ชั่นท้องถิ่น ฟังก์ชั่นท้องถิ่นสามารถใช้ได้เฉพาะภายในไฟล์

อย่างไรก็ตามการแก้ไขปัญหาที่แนะนำในคำตอบอื่น ๆ สามารถบรรลุสิ่งที่คล้ายกัน


นี่ไม่ใช่สิ่งที่ Gnovice ระบุไว้ในตอนต้นของคำตอบ?
Adiel

@Adiel บางที แต่หลายปีผ่านไปตั้งแต่คำตอบนั้นและบางคนอาจสงสัยว่ามีอะไรเปลี่ยนแปลง
Dev-iL

ฉันยังไม่ได้รับถ้ามีอะไรเปลี่ยนแปลง ... :)
Adiel

Nope นอกเหนือจากเอกสารบางอย่างที่เพิ่มเข้ามาเพื่อระบุหัวข้อนี้โดยเฉพาะ
Dev-iL

เหตุผลที่ฉันเขียนคำตอบนี้เป็นเพราะรุ่นที่ผ่านมาพวกเขาแนะนำฟังก์ชั่นที่คุณสามารถเพิ่มในตอนท้ายของสคริปต์ - ดังนั้นหนึ่งอาจสงสัยว่ามีอะไรเปลี่ยนแปลงในเรื่องนี้เช่นกัน (คำตอบ: ไม่)
Dev-iL

-1

ฉันได้ลองกับSCFRenchและกับRu Hashaในระดับแปดเสียง

และในที่สุดก็ใช้งานได้ แต่ฉันได้ทำการเปลี่ยนแปลงบางอย่างแล้ว

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

สามารถเรียกได้ในไฟล์ 'm' อื่น ๆ :

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

อัปเดต:

ฉันเพิ่มคำตอบเพราะทั้ง +72 และ +20 ไม่ทำงานในระดับแปดเสียงสำหรับฉัน งานที่ฉันเขียนนั้นสมบูรณ์แบบ (และฉันทดสอบเมื่อวันศุกร์ที่แล้วหลังจากที่ฉันเขียนโพสต์ในภายหลัง)


2
หากคุณสามารถอธิบายได้ว่าสิ่งนี้แตกต่างจากคำตอบที่มีอยู่สองคำตอบที่คุณกำลังคัดลอกมาอย่างไรฉันจะลบ downvote ของฉันออก ขออภัยที่ไม่ได้แสดงความคิดเห็นก่อนหน้านี้ ฉันไม่เห็นว่ามันจะแตกต่างกันอย่างไรถ้าคุณรวมทั้งสองวิธีเป็นหนึ่งฟังก์ชั่นดังนั้นจึงทำบางสิ่งซ้ำซ้อน นอกจากนี้โปรดใส่ลิงก์ที่เหมาะสมไปยังคำตอบที่คุณอ้างอิง "+72" และ "+20" ค่อนข้างเป็นความลับฉันใช้เวลาสักครู่ในการตระหนักว่าคุณกำลังอ้างอิงจำนวนการลงคะแนนซึ่งจะเปลี่ยนแปลงตลอดเวลาและทำการอ้างอิงของคุณ อ่านไม่ออก
Cris Luengo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.