MATLAB Language
Najlepsze praktyki MATLAB
Szukaj…
Uwagi
W tym temacie przedstawiono najlepsze praktyki, których społeczność nauczyła się z czasem.
Trzymaj linie krótkie
Użyj znaku kontynuacji (elipsa) ...
aby kontynuować długą instrukcję.
Przykład:
MyFunc( parameter1,parameter2,parameter3,parameter4, parameter5, parameter6,parameter7, parameter8, parameter9)
można zastąpić:
MyFunc( parameter1, ...
parameter2, ...
parameter3, ...
parameter4, ...
parameter5, ...
parameter6, ...
parameter7, ...
parameter8, ...
parameter9)
Poprawne wcięcie
Prawidłowe wcięcie nadaje nie tylko estetyczny wygląd, ale także zwiększa czytelność kodu.
Na przykład rozważ następujący kod:
%no need to understand the code, just give it a look
n = 2;
bf = false;
while n>1
for ii = 1:n
for jj = 1:n
if ii+jj>30
bf = true;
break
end
end
if bf
break
end
end
if bf
break
end
n = n + 1;
end
Jak widać, musisz dokładnie przyjrzeć się, która pętla i if
instrukcje kończą się gdzie.
Dzięki inteligentnemu wcięciu uzyskasz ten wygląd:
n = 2;
bf = false;
while n>1
for ii = 1:n
for jj = 1:n
if ii+jj>30
bf = true;
break
end
end
if bf
break
end
end
if bf
break
end
n = n + 1;
end
To wyraźnie wskazuje początek i koniec instrukcji loop / if
.
Możesz wykonać inteligentne wcięcie poprzez:
• zaznaczenie całego kodu ( Ctrl + A )
• a następnie naciskając Ctrl + I lub klikając z paska edycji.
Użyj potwierdzenia
Matlab pozwala na ciche pomijanie niektórych bardzo trywialnych błędów, które mogą spowodować, że błąd zostanie zgłoszony znacznie później w trakcie uruchamiania - utrudniając debugowanie. Jeśli zakładamy coś o zmiennych, zatwierdź go.
function out1 = get_cell_value_at_index(scalar1,cell2)
assert(isscalar(scalar1),'1st input must be a scalar')
assert(iscell(cell2),'2nd input must be a cell array')
assert(numel(cell2) >= scalar1),'2nd input must have more elements than the value of the 1st input')
assert(~isempty(cell2{scalar1}),'2nd input at location is empty')
out1 = cell2{scalar1};
Unikaj pętli
W większości przypadków pętle są drogie obliczeniowo w Matlabie. Twój kod będzie o rząd wielkości szybszy, jeśli użyjesz wektoryzacji. Często sprawia również, że kod jest bardziej modułowy, łatwo modyfikowalny i łatwiejszy do debugowania. Główną wadą jest to, że trzeba poświęcić czas na planowanie struktur danych, a błędy wymiarów są łatwiejsze do znalezienia.
Przykłady
Nie pisz
for t=0:0.1:2*pi
R(end+1)=cos(t);
end
ale
t=0:0.1:2*pi;
R=cos(t)
Nie pisz
for i=1:n
for j=1:m
c(i,j)=a(i)+2*b(j);
end
end
Ale coś podobnego do
c=repmat(a.',1,m)+2*repmat(b,n,1)
Aby uzyskać więcej informacji, zobacz wektoryzacja
Utwórz unikalną nazwę dla pliku tymczasowego
Podczas kodowania skryptu lub funkcji może się zdarzyć, że jeden lub więcej plików tymczasowych będzie potrzebnych na przykład do przechowywania niektórych danych.
Aby uniknąć zastąpienia istniejącego pliku lub zaciemnienia funkcji MATLAB, można użyć funkcji tymczasowej do wygenerowania unikalnej nazwy pliku tymczasowego w systemowym folderze tymczasowym.
my_temp_file=tempname
Nazwa pliku jest generowana bez rozszerzenia; można go dodać, tempname
pożądane rozszerzenie z nazwą wygenerowaną przez tempname
my_temp_file_with_ext=[tempname '.txt']
Lokalizację systemowego folderu tymczasowego można odzyskać, wyrywając funkcję tempdir .
Jeśli podczas wykonywania funkcji / skryptu plik tymczasowy nie jest już potrzebny, można go usunąć za pomocą funkcji delete
Ponieważ delete
nie prosi o potwierdzenie, to może być przydatne, aby ustawić on
opcję, aby przenieść plik do usunięcia w recycle
folderu.
Można to zrobić za pomocą funkcji recyklingu w ten sposób:
recycle('on')
W poniższym przykładzie zaproponowano możliwe użycie funkcji tempname
, delete
i recycle
.
%
% Create some example data
%
theta=0:.1:2*pi;
x=cos(theta);
y=sin(theta);
%
% Generate the temporary filename
%
my_temp_file=[tempname '.mat'];
%
% Split the filename (path, name, extension) and display them in a message box
[tmp_file_path,tmp_file_name, tmp_file_ext]=fileparts(my_temp_file)
uiwait(msgbox(sprintf('Path= %s\nName= %s\nExt= %s', ...
tmp_file_path,tmp_file_name,tmp_file_ext),'TEMPORARY FILE'))
%
% Save the varaibles in a temporary file
%
save(my_temp_file,'x','y','theta')
%
% Load the varaibles from the temporary file
%
load(my_temp_file)
%
% Set the reclycle option on
%
recycle('on')
%
% Delete the temporary file
%
delete(my_temp_file)
Zastrzeżenie
Tymczasowa nazwa pliku jest generowana przy użyciu metody java.util.UUID.randomUUID
( randomUUID ).
Jeśli MATLAB jest uruchamiany bez JVM, tymczasowa nazwa pliku jest generowana przy użyciu
matlab.internal.timing.timing
oparty na liczniku procesora i czasie. W takim przypadku tymczasowa nazwa pliku nie jest gwarantowana.
Użyj sprawdzania poprawności atrybutów
Funkcja validateattributes może być używana do sprawdzania poprawności tablicy względem zestawu specyfikacji
Można go zatem wykorzystać do sprawdzenia poprawności danych wejściowych funkcji.
W poniższym przykładzie funkcja test_validateattributes
wymaga trzech danych wejściowych
function test_validateattributes(input_1,input_2,input_3)
Dane wejściowe to:
tablica_1:
- klasa: podwójna
- rozmiar: [3,2]
- wartości: elementy nie mogą być NaN
char_array:
- klasa: char
- wartość: ciąg nie może być pusty
tablica_3
- klasa: podwójna
- rozmiar: [5 1]
- wartości: elementy muszą być prawdziwe
Aby sprawdzić poprawność trzech danych wejściowych, funkcję validateattributes
można wywołać za pomocą następującej składni:
validateattributes(A,classes,attributes,funcName,varName,argIndex)
gdzie:
-
A
to tablica, która ma zostać przeszukana -
classes
: totype
tablicy (np.single
,double
,logical
) -
attributes
: toattributes
które musi dopasować tablica wejściowa (np.[3,2], size
określający rozmiar tablicy, wartośćnonnan
określająca, że tablica nie będzie mieć wartości NaN) -
funcName
: jest nazwą funkcji, w której odbywa się sprawdzanie poprawności. Ten argument jest używany podczas generowania komunikatu o błędzie (jeśli występuje) -
varName
: to nazwa sprawdzanej tablicy. Ten argument jest używany podczas generowania komunikatu o błędzie (jeśli występuje) -
argIndex
: jest pozycją tablicy inpurt na liście danych wejściowych. Ten argument jest używany podczas generowania komunikatu o błędzie (jeśli występuje)
W przypadku, gdy jedno lub więcej danych wejściowych nie pasuje do specyfikacji, generowany jest komunikat o błędzie.
W przypadku więcej niż jednego nieprawidłowego wejścia sprawdzanie poprawności kończy się, gdy zostanie znalezione pierwsze niedopasowanie.
Jest to function test_validateattributes
w której zaimplementowano sprawdzanie poprawności danych wejściowych.
Ponieważ funkcja wymaga trzech danych wejściowych, pierwsze sprawdzenie liczby wprowadzonych danych jest przeprowadzane przy użyciu funkcji nargin .
function test_validateattributes(array_1,char_array_1,array_3)
%
% Check for the number of expected input: if the number of input is less
% than the require, the function exits with an error message
%
if(nargin ~= 3)
error('Error: TEST_VALIDATEATTRIBUTES requires 3 input, found %d',nargin)
end
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Definition of the expected characteristics of the first input %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% INPUT #1 name (only used in the generation of the error message)
%
input_1_name='array_1';
%
% INPUT #1 position (only used in the generation of the error message)
%
input_1_position=1;
%
% Expected CLASS of the first input MUST BE "double"
%
input_1_class={'double'};
%
% Expected ATTRIBUTES of the first input
% SIZE: MUST BE [3,2]
%
input_1_size_attribute='size';
input_1_size=[3,2];
%
% VALUE CHECK: the element MUST BE NOT NaN
%
input_1_value_type='nonnan';
%
% Build the INPUT 1 attributes
%
input_1_attributes={input_1_size_attribute,input_1_size, ...
input_1_value_type};
%
% CHECK THE VALIDITY OF THE FIRST INPUT
%
validateattributes(array_1, ...
input_1_class,input_1_attributes,'', ...
input_1_name,input_1_position);
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Definition of the expected characteristics of the second input %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% INPUT #1 name (only used in the generation of the error message)
%
input_2_name='char_array_1';
%
% INPUT #2 position (only used in the generation of the error message)
%
input_2_position=2;
%
% Expected CLASS of the first input MUST BE "string"
%
input_2_class={'char'};
%
% VALUE CHECK: the element must be not NaN
%
input_2_size_attribute='nonempty';
%
% Build the INPUT 2 attributes
%
input_2_attributes={input_2_size_attribute};
%
% CHECK THE VALIDITY OF THE SECOND INPUT
%
validateattributes(char_array_1, ...
input_2_class,input_2_attributes,'', ...
input_2_name,input_2_position);
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Definition of the expected characteristics of the third input %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% INPUT #3 name (only used in the generation of the error message)
%
input_3_name='array_3';
%
% INPUT #3 position (only used in the generation of the error message)
%
input_3_position=3;
%
% Expected CLASS of the first input MUST BE "double"
%
input_3_class={'double'};
%
% Expected ATTRIBUTES of the first input
% SIZE: must be [5]
input_3_size_attribute='size';
input_3_size=[5 1];
% VALUE CHECK: the elements must be real
input_3_value_type='real';
%
% Build the INPUT 3 attributes
%
input_3_attributes={input_3_size_attribute,input_3_size, ...
input_3_value_type};
%
% CHECK THE VALIDITY OF THE FIRST INPUT
%
validateattributes(array_3, ...
input_3_class,input_3_attributes,'', ...
input_3_name,input_3_position);
disp('All the three input are OK')
Poniższego skryptu można użyć do przetestowania wdrożenia procedury sprawdzania poprawności.
Generuje trzy wymagane dane wejściowe i, losowo, czyni je nieważnymi.
%
% Generate the first input
%
n_rows=randi([2 3],1);
n_cols=2;
input_1=randi([20 30],n_rows,n_cols);
%
% Generate the second input
%
if(rand > 0.5)
input_2='This is a string';
else
input_2='';
end
%
% Generate the third input
%
input_3=acos(rand(5,1)*1.2);
%
% Call the test_validateattributes function with the above generated input
%
input_1
input_2
input_3
%
test_validateattributes(input_1,input_2,input_3)
Oto kilka przykładów nieprawidłowych danych wejściowych wykrytych przez funkcję validateattributes
:
Błędne wejście
input_1 =
23 22
26 28
input_2 =
''
input_3 =
0.0000 + 0.4455i
1.2420 + 0.0000i
0.4063 + 0.0000i
1.3424 + 0.0000i
1.2186 + 0.0000i
Error using test_validateattributes (line 44)
Expected input number 1, array_1, to be of size 3x2 when it is actually
size 2x2.
Błędne wejście
input_1 =
22 24
21 25
26 27
input_2 =
This is a string
input_3 =
1.1371 + 0.0000i
0.6528 + 0.0000i
1.0479 + 0.0000i
0.0000 + 0.1435i
0.0316 + 0.0000i
Error using test_validateattributes (line 109)
Expected input number 3, array_3, to be real.
Prawidłowe wejście
input_1 =
20 25
25 28
24 23
input_2 =
This is a string
input_3 =
0.9696
1.5279
1.3581
0.5234
0.9665
All the three input are OK
Zablokuj komentarz operatora
Dobrą praktyką jest dodawanie komentarzy opisujących kod. Jest to pomocne dla innych, a nawet dla programisty, gdy zostanie zwrócony później. Pojedynczy wiersz można skomentować za pomocą symbolu %
lub skrótu Ctrl+R
Aby anulować komentarz do poprzednio komentowanego wiersza, usuń symbol %
lub użyj skrótu Crtl+T
Podczas gdy komentowanie bloku kodu można zrobić, dodając symbol %
na początku każdej linii, nowsze wersje MATLAB (po 2015a) pozwalają na użycie operatora komentowania bloków %{ code %}
. Ten operator zwiększa czytelność kodu. Może być używany zarówno do komentowania kodu, jak i dokumentacji pomocy funkcji. Blok można składać i rozkładać, aby zwiększyć czytelność kodu.
Jak widać operatory %{
i %}
muszą pojawiać się same w liniach. Nie umieszczaj żadnego innego tekstu w tych wierszach.
function y = myFunction(x)
%{
myFunction Binary Singleton Expansion Function
y = myFunction(x) applies the element-by-element binary operation
specified by the function handle FUNC to arrays A and B, with implicit
expansion enabled.
%}
%% Compute z(x, y) = x.*sin(y) on a grid:
% x = 1:10;
y = x.';
%{
z = zeros(numel(x),numel(y));
for ii=1:numel(x)
for jj=1:numel(y)
z(ii,jj) = x(ii)*sin(y(jj));
end
end
%}
z = bsxfun(@(x, y) x.*sin(y), x, y);
y = y + z;
end