【问题标题】:What happens if a function is also a variable in MATLAB?如果函数也是 MATLAB 中的变量会怎样?
【发布时间】:2023-03-14 13:33:01
【问题描述】:

标题可能听起来很奇怪。所以这里是例子。

length是一个在MATLAB中广泛使用的关键字或内部函数,有人保存了一个名为length的变量。

我可以毫无问题地运行以下脚本,但如果我将它放在函数中会产生错误(使用 R2015b)

有效的脚本

clear length;
length = [1 2 4];
la = length;
clear length;
b = length(la);

不起作用的功能

function test(a)
    length = [1 2 4];
    save('data.mat','length');
    clear length;
    load('data.mat');
    % load
    la = length;
    clear length;

    b = length(la); 
end

错误:引用已清除的可变长度。

为什么会这样? MATLAB 如何以不同的方式处理这些情况?这应该发生在其他功能/关键字上吗?

【问题讨论】:

  • 能否添加可重现的代码(以及实际错误)。
  • 实际错误是什么?它发生在哪里?我无法重现您的错误。
  • 在我的 Matlab 控制台中:Error using length Not enough input arguments. Error in loadtracts (line 9) la = length;
  • 仍然无法重现。我在 MATLAB R2015a 上,这是我的控制台的快照:i.stack.imgur.com/AslOZ.png。在这里,我创建了一个虚拟变量 length,将其设置为 5,将该变量保存到 MAT 文件中,清除工作区,再次加载它并尝试您在上面执行的分配。它有效。
  • ``` %% 脚本工作清晰长度;长度 = [1 2 4]; la = 长度;明确的长度; b = 长度(la); %% 函数不起作用函数 test(a) 长度 = [1 2 4];保存('data.mat','长度');明确的长度;加载('data.mat'); % 负载 la = 长度;明确的长度; b = 长度(la); % 错误:引用已清除的可变长度。 ```

标签: matlab variables namespaces keyword


【解决方案1】:

问题

根据in this answer 提供的描述,MATLAB 实际解析函数并确定函数的范围它实际执行函数之前。因此,它想知道(在运行函数之前)您是否打算将length 用作函数或变量。在您的情况下,它会看到您将其用作变量,因此您不能将其用作函数即使您清除了变量。

示范

  1. 所以实际上,如果我们执行以下操作,MATLAB 将根本无法调用我们的函数:

    function test()
        %// Use length the function
        L = length([1,2,3]);
    
        %// Now use length as a variable
        length = 2;
    end
    

    错误:文件:test.m 行:6 列:6
    “长度”以前似乎被用作函数或命令,与这里用作 变量的名称。
    此错误的一个可能原因是您忘记初始化变量,或者您已初始化 它隐式使用 load 或 eval。

  2. 现在,如果我们改变我们的函数,以便我们首先调用 length 作为一个函数,然后加载我们的文件并尝试访问 变量 length(它被隐式初始化为 @987654327 @)

    function test()
        %// Use the function length
        L = length([1,2,3]);
    
        %// Load the variable length
        load('data.mat') 
        la = length;
    end
    

    使用长度时出错
    输入参数不足。

    因为 MATLAB 事先确定了函数的范围,所以它只看到了 函数 length,这会阻止 length 在函数后面用作变量,即使您尝试从文件中加载它。这样,当您尝试访问 变量 length 时,它的行为就像您在没有输入的情况下调用了 函数 length

    我们没有从 #1 中看到相同错误的原因是因为 MATLAB 无法知道 data.mat 包含一个名为 length 的变量,并且无法提醒您这种意外行为。

  3. 现在您注意到了,使用eval 实际上允许您访问变量。为什么会这样,我不完全确定,但eval 的范围很可能是在您调用它时确定的,并且不受父函数的范围规则的约束。

    eval 似乎试图在运行时确定是使用函数还是变量版本 length,因为我们可以让它在同一个函数中确认两者。

    function test()
        %// Use the function length
        L = length([1,2,3]);
    
        %// Load the variable length
        load('data.mat')
    
        %// Eval can actually access the VARIABLE length
        eval('la = length;');
    
        %// Eval can ALSO access the FUNCTION length
        eval('L = length([1,2,3])');
    end
    

总结

所以这实际上意味着,如果您在函数中定义一个名为 length 的变量,MATLAB 将在运行您的函数之前确定 ,从而阻止您将 length 用作function 在同一个函数中。使用脚本或在命令窗口中不会出现此问题,因为范围是在运行时计算的,length 可以用作变量和函数(假设您在调用函数 @987654344 之前调用了 clear length @)。

解决方案

最佳做法是始终 specify an output to load。然后将数据作为struct 加载,而不是使用存储在文件中的所有变量污染当前工作区。那么无论什么用户命名变量都没有关系,它保证不会与您的任何变量或 MATLAB 的内置函数发生冲突,并且您可以避免意外行为。

data = load('data.mat');
la = data.length;

这也确保了 MATLAB 能够正确确定函数的范围,因为它可以看到您有一个名为 data 的变量,并且 data.mat 的所有内容都将加载到该变量中。

如果你必须

如果您想保持原样,但在加载文件后仍然可以访问内置的length 函数(不指定输出参数)。您可以使用builtin 访问real length 函数。

b = builtin('length', la);

【讨论】:

  • 谢谢,这绝对是一个比避免保留关键字或使用的函数名更好的经验法则。如果像我上面编辑的代码一样,你能告诉我为什么它在函数内部和外部的工作方式不同吗?
  • @KangqiaoZhao 我添加了更详尽的描述,描述了您所看到的差异,包括eval 的使用。检查一下,如果不清楚,请告诉我。
猜你喜欢
  • 2013-08-07
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 2011-04-27
相关资源
最近更新 更多