MATLAB中是否可能存在自引用?

23

正如这里所述,即使是包中的函数以及类中的静态方法,仍然需要使用packagename.functionname语法或者import packagename.*来引用每个函数(因为导入是函数工作空间的一部分而非全局)。这意味着后续更改包名或类名可能会变得繁琐。

有没有办法实现像import this.*这样的东西?也就是说,是否有一种与包名/类名无关的方法可以访问同一包/类中的所有函数/静态方法?


我很想听到这个问题的答案... - Andrey Rubshtein
@Andrey 我也是这样想的。或许悬赏会有助于找到一些巧妙的方法... 顺便说一下,Gnovice发现了一个不错的技巧,但正如他所说,这可能会浪费大量的计算时间。 - Tobias Kienzler
4
如果我们给它足够的赞,也许他们会在R2012a中添加它? - Andrew Janke
@Andrew 当然,试试看吧;-) 在那之前,我想这里的“正确”答案就是简单地“不行,但如果你真的需要它,使用Gnovice这个Hack”。 - Tobias Kienzler
@AndrewJanke ...还是R2019a? - Rody Oldenhuis
我什么也没有。据我所知,没有任何变化,import 仍然限定于函数/方法的作用域,而不是类定义,并且没有 import this.*。我也没有听说 R2019a 有任何变化。也许是在 R2021a? :) - Andrew Janke
3个回答

8

所以...这不需要导入importthis吗?或者importthis是你的路径中总是有的函数吗?

似乎只需在每个函数顶部粘贴一个带有此内容的"import this"块,就不必担心importthis是否在您的路径中。我倾向于觉得依赖路径是危险的。

"Import This" 块

%% Import own package
[~, pkgdir] = fileparts(fileparts(mfilename('fullpath')));
import([pkgdir(2:end) '.*']);

您甚至可以将其放在try/catch块中,以确保它在包目录中,并决定如果不是,则该怎么办。
%% Import own package
try
    [~, pkgdir] = fileparts(fileparts(mfilename('fullpath'))); 
    import([pkgdir(2:end)'.*']);
catch err
    if ~strcmp(err.identifier,'MATLAB:UndefinedFunction'), rethrow(err); end
end

2
甚至可以为嵌套包使用类似以下的代码:
mfiledir = fileparts(mfilename); pkg_pos = strfind(mfiledir, [filesep '+']); if ~isempty(pkg_pos), import([strrep(mfiledir((pkg_pos(1)+2):end), [filesep '+'], '.') '.*']); end
- Ken Chatfield

4

我最近遇到了一个类似的问题,并找到了以下关于包的解决方法。然而,这种方法非常hacky。

您可以创建一个名为import this的函数,其中包含一个可选参数。

function to_eval = importthis(exclude_list)
if nargin == 0
    exclude_list = [];
end
var_name = genvarname('A', exclude_list); %avoid shadowing
to_eval = ['[~,'...
    , var_name...
    , ']=fileparts(fileparts(mfilename(''fullpath'')));'... %get containing dir
    , 'eval([''import '','...
    , var_name...
    , '(2:end),''.*'']);'... %remove '+'
    , 'clear '... %clean up
    , var_name
    ];
end

该函数返回一个字符串,该字符串可以被 eval ,用于导入 "this" 包。因此,在您的包函数中,您需要在顶部附近放置以下内容:
function B = myfunc(A)
eval(importthis);
%function body
end

您还可以将who参数传递给importhis函数,这样可以使您的函数命名空间更加清晰。
function B = myfunc(A)
eval(importthis(who));
%function body
end

我无法决定我应该为自己的所作所为感到骄傲还是厌恶。


1
干得好!我猜如果你使用evalin('caller',...),你可以省去外部的eval并直接调用importthis。这也是如何将目录转换为包?的答案。 - Tobias Kienzler
我尝试了 evalin 但似乎不起作用。也可以在不使用 eval 的情况下获取包|目录名称。您可以抛出一个虚拟异常,捕获它并检查它,因为它包含堆栈跟踪。或者您可以滥用 dbstack。除此之外,我的解决方案与您链接的解决方案相同。 - AE426082

3
这可能不是一个值得悬赏的答案,但由于你没有任何答案,我想无论如何都会发布它!您可以通过类的实例调用静态方法,您只需要定义一次即可。您可以通过函数句柄调用函数,但这将需要每个函数一个句柄。
使用这些技术,您可以在一个地方定义所有静态方法和函数引用。然后,您将在整个程序包中使用这些引用。然后,如果您决定在以后更改程序包名称,则只需要更新这些引用,这些引用都存储在一个地方。
参见: 调用静态方法 你也可以像调用任何方法一样使用实例来调用静态方法:
obj = MyClass; value = obj.pi(.001); function_handle (@) 以下示例创建了一个函数句柄,用于 humps 函数,并将其分配给变量 fhandle。
fhandle = @humps;

好吧,浪费赏金也是件遗憾的事情 :-7 但你的回答可能是目前最接近实现的,所以感谢您发布它。 - Tobias Kienzler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接