如何获取从句柄到 Matlab 中方法的输出数量?

Posted

技术标签:

【中文标题】如何获取从句柄到 Matlab 中方法的输出数量?【英文标题】:How to get the number of outputs from a handle to a method in Matlab? 【发布时间】:2017-05-11 23:35:12 【问题描述】:

您可以使用函数句柄调用对象的方法。示例:

classdef foo
  methods
    function value=foofun(this)
      value=1;
    end
  end
end

然后

fun=@foofun;
fun(foo);

我猜句柄只是一个字符串,它不会打扰Matlab,它在使用句柄之前无法判断哪个函数是预期的。如果使用不同类型的对象作为第一个参数,甚至可以使用相同的句柄来调用不同的方法。

要捕获函数的输出,您可以这样做:

outputs=cell(numberOfOutputs,1);
[outputs:]=fun(foo);

但是,如果函数句柄是代码中的一个参数,那么输出的数量就是一个问题。对于普通函数的句柄,nargout 可以解决这个问题,但现在 nargout 无能为力,因为句柄不能自行确定将调用哪个函数。 nargout 需要第二个输入,即要使用的对象的类型。

同时需要句柄和输出数量作为参数有点不雅。是否有另一种方法可以间接调用方法并仍然捕获所有输出?

用例

想象一个有节点和节点之间的边的图。每条边都有一些与该特定边相关的数据对象。我有兴趣对这些数据对象进行各种计算。

示例

获取与特定边缘关联的所有数据对象并计算这些对象的光谱。 使用每个边缘中最漂亮的数据对象并从这些对象中获取光谱。 随机选择十条边,从每条边中随机选择一个数据对象,然后将这些对象与一个特定的单独对象进行比较。

设计

这个想法是将对象的选择和计算分成不同的功能。这样,用户可以将任何计算与任何选择方法结合起来。每次向数据对象添加新方法时,已经可以与现有的对象选择方法一起调用,每次添加新的选择方法时,都可以与所有可用的计算方法一起使用。

我当前使用的函数的简化版本如下所示

function [ outs ] = callForEach(objects, fun, numberOfOutputs, extraArguments)
    for ii=1:length(objects)
      out=cell(1,numberOfOutputs);
      [out:]=fun(objectsii,extraArgumentsii,:);
      outs(ii,:)=out;
    end
end

我希望能够避免参数 numberOfOutputs。这给用户带来了不便,而且这样做更容易出错。

我想我可以为每个方法强制使用相同的接口:如果他们需要多个输出,每个人都会返回一个元胞数组。然后我可以将该单元格数组或返回的任何内容分配到单个单元格中。但是,所有内置函数似乎都更喜欢使用多个输出,因此至少存在风格上的差异。如果我想使用其中一个内置函数作为句柄,我需要编写一个包装器以使内置函数符合接口。

【问题讨论】:

这个的预期用例是什么?通常,当库函数需要一个函数句柄并指定句柄必须匹配的预期接口时,需要通过函数句柄进行间接调用(例如,ode45odefun 和可选的Events 句柄)。传递类实例并直接对其进行操作会更容易。 编辑回答了我的大部分问题,除了“手柄的预期界面是什么?”我看到@prettiest 应该采用edges 的数组并返回最漂亮的数组;并且@spectrum 应该对dataObjects 的数组进行操作并返回关联的sepctra 数组。多个输出在哪里? 我实际上认为@spectrum 只对单个对象进行操作,因此调用它的人可以决定是否并行化调用。但是,这种差异并不重要。 我仍然不知道未知数量的输出在哪里起作用。此外,您是否打算让用户访问绑定到这些正在播放的对象的这套方法?如果是这样,您可以根据this.(nameOfMethod)(x); 之类的字符串动态调用它们,并可能用用户定义的方法字符串替换对句柄的需求。 对不起,我不明白缺少什么。 :D 方法集自然绑定到游戏中的对象,它们是方法(类的成员),而不是函数。 this.(nameOfMethod)(x) 我猜是另一种选择,但我认为这没有什么不同。方法的签名不同,所以我不知道我应该尝试捕获多少返回。 【参考方案1】:

检查这个类为foo.m。通过运行foo.main(),您可以恢复大部分已解决的问题。

这不是 OOP 中最大的优雅,但你有 Matlab。

记住obj 变量是MANDATORY,进出。没有obj,没有点花哨。

最后的调用,必须包含f1。放置~ 不仅失去了花哨,还失去了对象及其数据。

除了obj 处理之外,nargin|nargout|varargin|varargout 仅在函数体内有效,并且与往常一样取决于运行时。人们一般无法知道你会抛出多少参数,因为它相当于可变参数单元格的长度。

classdef foo
    properties
        value;
    end
    methods
        function [obj,flag]=fun1(obj,this)
            obj.value=this+1;
            flag=1;
        end
        function [obj,flag]=fun2(obj,this)
            obj.value=2*this;
            flag=2;
        end
        function [obj,varargout]=fun3(obj,varargin)
            for i=1:nargin-1
                varargouti=varargini;
            end
            obj.value=0;
        end
    end
    methods (Static)
        function main()
            if 0
                %% Run this line
                foo.main()
            end
            f1=foo();
            [f1,flag]=f1.fun1(10);
            flag
            f1.value
            f=@fun2;
            %[f1,flag]=f1.f(10); % fails
            flag
            f1.value
            [f1,flag]=f1.('fun2')(10);
            flag
            f1.value
            [~,flag]=f1.fun2(10); % fails
            flag
            f1.value
            [f1,a1,a2,a3,a4]=f1.fun3('x1',2,[],@(x)(x>1))
        end
    end
end

【讨论】:

以上是关于如何获取从句柄到 Matlab 中方法的输出数量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MATLAB 中获取所有打开图形的句柄

如何在Matlab中调用afterEach后得到函数句柄的输出?

Matlab:如何获取图形句柄中的所有轴句柄?

Win32获取屏幕句柄的函数是啥?

matlab调整legend方框大小

如何在matlab中将句柄对象层次结构保存到磁盘