【问题标题】:Is it possible to enforce input argument data types in MATLAB?是否可以在 MATLAB 中强制执行输入参数数据类型?
【发布时间】:2014-03-02 07:08:59
【问题描述】:

我想确保用户定义的 MATLAB 函数(包含在 m 文件中)的输入参数属于特定类型。我知道 MATLAB 会自动将数据类型分配给变量(某些人喜欢而另一些人对此感到沮丧),但我想知道 MATLAB 中是否有“严格数据类型”选项或类似的选项,尤其是用于用户定义函数的输入参数。

我在这两个网页上找到了关于 MATLAB 的“基本类”(数据类型)的有用解释:

http://www.mathworks.com/help/matlab/matlab_prog/fundamental-matlab-classes.html http://www.mathworks.com/help/matlab/data-types_data-types.html

但是,我一直无法找到严格数据类型问题的答案,尤其是对于函数输入参数。我认为这将是一个非常基本的问题,已经在很多地方得到了回答,但是经过广泛的搜索,我还没有找到一个决定性的答案。目前,我一直在使用 is[TYPE]() 函数手动检查数据类型,如果不符合则显示错误消息,尽管这看起来很草率,我希望我可以让 MATLAB 为我强制执行它。

下面是一个函数示例,我想在其中指定输入参数数据类型。它位于 MATLAB 当前路径中名为 strict_data_type_test.m 的文件中。在这个函数中,我想强制变量 yes_or_no 是 MATLAB 的 logical 数据类型。我知道我可以使用 islogical() 函数手动检查,但我的问题是是否可以让 MATLAB 为我强制执行它。我也知道任何非零双精度计算结果为真,零计算结果为假,但我想强制用户发送 logical 以确保错误的参数不是意外发送的,例如。这是示例函数:

function y = strict_data_type_test( x, yes_or_no )

    % manual data type check can go here, but manual check is not desirable

    if (yes_or_no)
        y = 2 .* x;
    else
        y = -5 .* x;
    end

end

在输入参数变量名称之前添加数据类型(就像在大多数编程语言中一样)将数据类型文本视为另一个变量名称而不是数据类型标识符。由此看来,无论如何,在 MATLAB 中严格的数据类型是不可能的,但也许你们中的许多大师都知道我无法找到的有用的技巧、特性或语法。

【问题讨论】:

  • 答案是否定的。你所谓的is[TYPE]() 就是这样做的方法。或阅读inputParserhere。或者,如果您愿意,也可以编写 mex 函数。如果强制执行类型并且用户传入了错误的类型,您会发生什么?
  • 我同意其他人的观点,inputParser 是要走的路。有关摘要和简明示例,请参阅 here
  • 回应 horchler:我希望如果有类型强制并且用户从控制台传入了错误的类型,那么会发生错误(无需我在函数),更重要的是,如果用户在另一个脚本或函数中键入函数调用,那么 MATLAB 会将函数调用突出显示为错误,向用户显示它是不正确的,而无需运行脚本/函数(“编译器强制执行” )。

标签: matlab function types


【解决方案1】:

validateattributes 也可能对您有用,如果有适合您的情况的属性。例如,如果您想强制 yes_or_no 是一个逻辑标量,您可以尝试:

validateattributes(yes_or_no,{'logical'},{'scalar'})

否则可能是像“非空”这样的属性。

【讨论】:

  • 您可以使用用户定义的类,因此它适用于任何输入类型。我经常使用它。
【解决方案2】:

我得到了一些很好的回应,所以我不能只选择一个作为“接受的答案”,而是总结一下我到目前为止从你们那里学到的东西:

  • 不,MATLAB 没有内置的函数输入参数的严格数据类型
  • MATLAB 在运行之前编译代码,因此手动验证检查不应该对性能造成很大负担(分析器可用于评估这一点)
  • 存在许多进行手动验证检查的有用方法,此处按与我尝试执行的操作最相关到最不相关的顺序列出:
  • 我可以查看一些 MathWorks 提供的 MATLAB 函数(或 Statistics 工具箱函数),了解如何通过键入 edit 后跟函数名称来验证输入参数。两个建议的函数是normpdf()(来自统计工具箱)和integral()。我发现其他一些有用的函数是 dot()cross()

其他想法:

  • 看来inputParser 类是对验证输入参数的最专业方法的总体共识。 a related (but not duplicate) stackoverflow post 上指出,较新的 MathWorks 函数倾向于使用这个类,这表明它可能是最好和最新的选择。
  • 由于 MathWorks 提供的 MATLAB 函数似乎没有强制执行严格的输入参数数据类型,这进一步表明即使可以这样做,也可能不是推荐的方法。
  • MATLAB 似乎将“错误处理”和“异常处理”视为两个不同的概念。例如,这里有两个指向 MATLAB 文档中心的链接,它们展示了 MathWorks 如何以不同的方式考虑“错误处理”和“异常处理”:MathWorks Documentation Center article on Error HandlingMathWorks Documentation Center article on Exception Handling。已就该主题发表了相关的 StackOverflow 帖子,可以在 here (link) 找到。我联系了 MathWorks,并在该帖子中添加了有关此主题的一些新信息,因此,如果您有兴趣,可以点击该链接阅读更多信息。

【讨论】:

    【解决方案3】:

    Matlab 提供了一个“inputParser”,它允许检查输入。除此之外,您还可以使用断言:

    assert(islogical(yes_or_no),'logical input expected')
    

    为确保输入参数的数量正确,请使用narginchk

    顺便说一句:看看一些 Matlab 函数,如 edit integral 并检查 tmw 如何处理这个问题。

    【讨论】:

    • edit integal 是错字吗?我发现edit 似乎在编辑器中打开文件,我认为integalintegral 的拼写错误。所以你是说我应该看看内置 MATLAB 函数的代码,比如integral,看看它们是如何强制输入参数数据类型的?
    • 是的,integal 是一个错字。对于架构/模式的问题,我经常看一些内置函数,假设语言的设计者知道如何使用它;)
    【解决方案4】:

    您可能会发现编写此类代码很乏味或担心它会降低性能:

    if ~islogical(yes_or_no) && ~isscalar(yes_or_no)
        error('test:NotLogicalType','Second argument must be logical (Boolean).');
    end
    if yes_or_no
        y = 2 .* x;
    else
        y = -5 .* x;
    end
    

    但是,请回想一下,Matlab 在运行之前会编译代码,因此即使您需要测试许多条件,它也会非常快。运行分析器来查看。

    在某些情况下(可能不是您的示例)的另一种选择是使用更惰性的方法。此选项允许您的代码使用提供的任何输入运行,但使用try/catch 块来捕获任何错误:

    try
        if yes_or_no
            y = 2 .* x;
        else
            y = -5 .* x;
        end
    catch me
        ...
        error('test:NotLogicalType','Second argument must be logical (Boolean).');
        % rethrow(me);
    end
    

    例如,如果yes_or_no 是一个元胞数组,上面的代码会产生错误(尽管它仍然允许yes_or_no 使用非布尔值、非标量等值,但Matlab 通常过于宽容)。然后,您可以生成自定义错误消息、检测、引发什么样的错误并尝试其他方法等。统计工具箱中的许多功能都使用这种方法(例如,在命令窗口中键入 edit normpdf)以获得更好的效果或更糟。

    【讨论】:

    • 但是如果x不能乘以-5也可能会抛出异常(可能是图形句柄?)。
    猜你喜欢
    • 2018-08-20
    • 2020-05-12
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    • 2018-09-26
    相关资源
    最近更新 更多