2009-04-09 33 views
12

Cho một chức năng như:nargin vs tồn tại

function foo(myParam) 
if nargin<1 
    myParam = 'default value'; 
end % if 
end % function 

Tôi đã nhìn thấy mọi người sử dụng một cái gì đó như sau trong vị trí của phiên bản nargin

if ~exist('myParam', 'var') 
    myParam = 'default value'; 
end %if 

Tôi đang tự hỏi nếu có bất kỳ sở thích theo cách nào?

Phiên bản "~ tồn tại ..." với tôi có lợi thế là nếu tôi thay đổi thứ tự các tham số chức năng của mình thì nó vẫn hoạt động. Tuy nhiên, mối quan tâm của tôi với phương pháp này là tôi vô tình có thể nhận các biến được xác định trên toàn cầu hoặc trong phạm vi của một hàm xung quanh trong trường hợp hàm lồng nhau.

Bất kỳ suy nghĩ nào về vấn đề này?

Trả lời

10

Cả hai đều hoạt động. Nhưng ...

Hiện có xu hướng chậm, vì phải xem qua không gian làm việc của bạn cho biến được đề cập. Khi bạn viết kiểm tra lỗi như thế này, bạn không muốn chúng hút các chu kỳ CPU. Thử nghiệm đối với nargin là một thử nghiệm đơn giản đối với một giá trị số duy nhất.

Tôi cũng thường đề xuất một thử nghiệm rộng hơn. Một cái gì đó như

if (nargin<1) || isempty(myparam) 

    myparam = defaultvalue; 

elseif 

    ... 

end 

Bên trong chi nhánh elseif, tôi sẽ đặt một loạt các thử nghiệm bổ sung cho thấy nếu tham số có kích thước dự kiến, hình dạng, loại biến, vv Nếu những thử nghiệm thất bại, tôi sẽ trở lại một thông báo lỗi thân thiện giải thích những gì đã sai.

7

tôi sẽ đi với nargin vì hai lý do:

  1. Nếu bạn thay đổi thứ tự của các tham số để hàm của bạn, sửa chữa lên đầu vào kiểm tra mã sẽ là ít nhất các vấn đề của bạn; bạn sẽ phải cập nhật tất cả các trang web gọi đến chức năng của bạn.

  2. nargin rẻ hơn nhiều. tồn tại, ngay cả khi scoped để chỉ kiểm tra các biến, đã quét toàn bộ không gian làm việc thực hiện một loạt các so sánh chuỗi trên đường đi. phương pháp nargin chỉ bao gồm một vô hướng nhỏ hơn hoạt động.

4

Tôi luôn xác thực đối số bằng cách sử dụng nargchk và sau đó đi kèm với các bài kiểm tra nargin khi bạn có chúng. Như những người khác đã chỉ ra, chúng rẻ hơn, và tôi nghĩ rõ ràng hơn.

Trong các chức năng mà tôi mong muốn được sử dụng lại nhiều, tôi luôn đặt rất nhiều kiểm tra lên phía trước và sau đó cấu trúc mã để gọi triển khai thực sự sau này.

Tôi cũng có xu hướng cấu trúc đối số tùy chọn (khi không sử dụng varargin) như thế này:

function x = myfcn(arg1, opt_arg2) 
if nargin < 2 
    arg2 = 'default'; 
else 
    arg2 = opt_arg2; 
end 

như tôi nghĩ điều này làm cho nó rõ ràng hơn khi chỉnh sửa các tập tin mà đối số được dự kiến ​​sẽ được bắt buộc.

4

Tôi muốn sử dụng tùy chọn NARGIN, vì các lý do được liệt kê theo SCFrench.Một lợi ích nữa: Tôi thường thấy mình sử dụng nó kết hợp với một tuyên bố SWITCH khi tôi có nhiều hơn 2 đối số đầu vào:

function outArgs = my_fcn(inArg1,inArg2,inArg3) 
    switch nargin, 
    case 0, % No input case 
     error('Not enough inputs!'); 
    case 1, % Set last 2 inputs to default 
     inArg2 = 'yes'; 
     inArg3 = 'on'; 
    case 2, % Set last input to default 
     inArg3 = 'on'; 
    end 
    ... 
    % Checking of variable types and values would go here! 
    ... 
end 
+0

Điều này có vẻ tiện dụng, nhưng tôi tự hỏi, nếu mà đi kèm với một màn trình diễn hình phạt ... – embert

3

Đối với những người sử dụng MATLAB R2007b hay muộn,
đây là một câu trả lời tốt hơn: InputParser

Nó tiết kiệm được sự cố khi phải đồng bộ hóa bất kỳ bổ sung, xóa, đổi tên và sắp xếp lại các đối số.

(Bao nhiêu bạn tiết kiệm sẽ phụ thuộc vào phong cách mã hóa của bạn, nhưng không có một cách gọn gàng hơn InputParser.)

tôi đã không kiểm tra nó cho tốc độ, nhưng nếu bạn có chức năng phải mất hơn 1000 mili giây để chạy, không có lý do gì để được quan tâm bởi tốc độ của InputParser.

Ví dụ:

function AbCdEfGhIj(ffff, ggggg, varargin) 
opts = inputParser; 
opts.addRequired('ffff', @(p)(ischar(p) && size(p,1)==1 || iscell(p))); 
opts.addRequired('ggggg', @(p)(iscell(p) && all(cellfun(@ischar,p)))); 
opts.addOptional('Recursive', false, @islogical); 
opts.addOptional('IncludeFullPath', logical([]), @islogical); 
opts.parse(ffff, ggggg, varargin{:}); 
opts = opts.Results; 
if isempty(opts.IncludeFullPath), 
    opts.IncludeFullPath = iscell(opts.fffff) || opts.Recursive; 
end 
2

tôi rất thích exist qua tùy chọn nargin vì hai lý do.

1. Sau khi đọc rất nhiều mã từ những người chưa bao giờ được dạy để nhìn lại mã riêng của họ, tôi đã chỉ cảm thấy mạnh hơn cho điều này, như exist làm cho đoạn code có thể đọc được. Ví dụ, tôi gặp phải một khi một chức năng như thế này. Để thuận tiện cho bạn, tôi đã đặt cho các biến hợp lý tên:

[model, accuracy] = epicModelingFunction (dataMatrix, responseVector, indicatorForCategoricalVariables, optionsForInternalFunctions, typeOfDistanceCalculation, notationForMissingValues, isClassificationAndNotRegression, scalingMethod, shouldPlotAllIntermediateStuff) 
% EPICMODELINGFUNCTION is actually a horrible function to read and not epic at all 
% ... 

Sau đó, sau đó là if nargin < n cho mỗi biến khác với hai biến số đầu tiên. Lý do duy nhất tôi có thể làm theo những gì các nargin(n) nên được mà không đếm đầu vào tiêu đề, là if nargin < n luôn được theo sau bởi (chỉ đôi khi một vài dòng mã và) khai báo đầu vào bị thiếu với giá trị mặc định. Đối với mâm mã lớn hơn trong if nargin < n, tôi chắc chắn sẽ mất dấu vết.

2.exist không thực sự kiểm tra không gian làm việc hoàn chỉnh nếu gọi từ một hàm. Chắc chắn, so sánh hai con số là ít tốn kém như so sánh một vài chuỗi, nhưng nếu được sử dụng ở đầu của một hàm để điền vào các giá trị mặc định cho các tham số không được đưa ra, nó là tốt. Hãy xem xét các chức năng sau:

function testExist(C) 
if exist('B', 'var') 
    disp('''exist'' in a function checks the workspace.') 
elseif exist('C', 'var') 
    disp('''exist'' in a function ignores the variables in the workspace, but checks the function space.') 
else 
    disp('''exist'' is broken or no parameter was given.') 
end 
end 

Và sau đó thực hiện như sau:

A = magic(3); 
B = magic(4); 
testExist(A) 

kết quả ở đầu ra này:

'exist' in a function ignores the variables in the workspace, but checks the function space. 
Các vấn đề liên quan