Matlab中类似于Python的yield关键字是什么?

7

我需要生成多个结果,但是一次只生成一个,而不是在数组中一次性生成所有结果。

我应该如何在Matlab中使用类似Python的生成器语法实现这个功能?


7
我认为Matlab没有惰性求值。 - senshin
看一下 varargout,这可能会解决你的问题。 - Daniel
2
如果内存不足,那么varargout无法解决问题。 - Frames Catherine White
一些相关的参考资料:协程生成器迭代器惰性求值 - Amro
2个回答

13

使用含有 yield 关键字的函数时,它们会返回一个生成器。生成器是迭代器的一种类型。虽然 MATLAB 不提供两者的语法,但您可以自己实现“迭代器接口”。下面是一个类似于 Python 中的 xrange 函数的示例:

classdef rangeIterator < handle
    properties (Access = private)
        i
        n
    end

    methods
        function obj = rangeIterator(n)
            obj.i = 0;
            obj.n = n;
        end

        function val = next(obj)
            if obj.i < obj.n
                val = obj.i;
                obj.i = obj.i + 1;
            else
                error('Iterator:StopIteration', 'Stop iteration')
            end
        end

        function reset(obj)
            obj.i = 0;
        end
    end
end

这是我们如何使用迭代器:

r = rangeIterator(10);
try
    % keep call next() method until it throws StopIteration
    while true
        x = r.next();
        disp(x);
    end
catch ME
    % if it is not the "stop iteration" exception, rethrow it as an error
    if ~strcmp(ME.identifier,'Iterator:StopIteration')
        rethrow(ME);
    end
end

请注意,在Python中使用迭代器时,使用for .. in ..结构时,它内部会执行类似的操作。

您可以使用常规函数而不是类来编写类似的内容,通过使用persistent变量或闭包来存储函数的本地状态,并在每次调用函数时返回“中间结果”。


啊,被我哭泣的儿子打断了。我正在编写一个解决方案,可以在构造函数中接受函数句柄。无论如何,+1。 - Jonas
1
如果你适当地重载迭代器的 size(返回 [1,n])和 subsref 方法,甚至可以简单地保持正常的 for .. in ... 语法。 - sebastian

6

在MATLAB中(在Octave中好像不行),你可以使用封闭函数(嵌套的作用域函数):

function iterator = MyTimeStampedValues(values)

    index = 1;

    function [value, timestamp, done] = next()
        if index <= length(values)
            value = values(index);
            timestamp = datestr(now);
            done = (index == length(values));
            index = index + 1;
        else
            error('Values exhausted');
        end
    end

    iterator = @next;
end

然后

iterator = MyTimeStampedValues([1 2 3 4 5]);
[v, ts, done] = iterator();    % [1, '13-Jan-2014 23:30:45', false]
[v, ts, done] = iterator();    % ...

1
这在MATLAB R2013b中运行得非常好,但是values是在调用MyTimeStampedValues时构建的。因此,实际上并没有任何惰性评估。 - Lumen
1
@Lumen 这个例子里面生成的不是数字,而是时间戳,它们是延迟生成的。原则上它能够完成任务,且在 Python 中 yield 仅仅是一个简化版。它实现了在调用之间保留状态的功能。 - Trilarion

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