加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

什么是Perl版本的Python迭代器?

发布时间:2020-12-15 21:26:36 所属栏目:大数据 来源:网络整理
导读:我在我的工作中学习Perl并享受它。我通常做我的工作在Python,但老板想要Perl。 Python和Perl中的大多数概念很好地匹配:Python dictionary = Perl hash; Python tuple = Perl列表; Python列表= Perl数组;等等 问题:是否有一个Perl版本的Iterator / Generat
我在我的工作中学习Perl并享受它。我通常做我的工作在Python,但老板想要Perl。

Python和Perl中的大多数概念很好地匹配:Python dictionary = Perl hash; Python tuple = Perl列表; Python列表= Perl数组;等等

问题:是否有一个Perl版本的Iterator / Generator的Python形式?

一个例子:生成斐波纳契数字的经典Python方法是:

#!/usr/bin/python

def fibonacci(mag):
     a,b = 0,1
     while a<=10**mag:
         yield a
         a,b = b,a+b

for number in fibonacci(15):  
     print "%17d" % number

如果您想根据需要生成大得多的列表的子部分,迭代器也很有用。 Perl’lists’似乎更加静态 – 更像是一个Python元组。在Perl中,foreach可以是动态的还是只基于静态列表?

Iterator的Python形式是一个我已经习惯了的形式,我没有发现它在Perl中记录…除了在循环或递归或生成一个巨大的静态列表,我如何(为ex)写在Perl的斐波那契子程序?有没有我缺少的Perl产量?

具体 – 我怎么写这个:

#!/usr/bin/perl
use warnings; use strict; # yes -- i use those!

sub fibonacci {
   # What goes here other than returning an array or list? 
}

foreach my $number (fibonacci(15)) { print $number . "n"; }

感谢提前对新人的亲切…

解决方法

为了比Python的生成器更灵活的解决方案,我已经在CPAN上编写了模块 List::Gen,它提供了随机访问延迟生成器数组:
use List::Gen;

my $fib; $fib = cache gen {$_ < 2  ? $_ : $$fib[$_ - 1] + $$fib[$_ - 2]};

say "@$fib[0 .. 15]";  #  0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610

因为生成器假装是数组,所以它们可以与正常的perl代码无缝地混合。还有一种面向对象的方法:

my $fib; $fib = cache gen {$_ < 2 ? $_ : $fib->get($_ - 1) + $fib->get($_ - 2)};

say join ' ' => $fib->slice(0 .. 15);

在每种情况下,生成器是惰性的,在创建时不计算任何值,然后仅计算满足切片所需的值。斐波那契序列的递归定义调用自身多次,因此缓存函数用于确保每个值只计算一次。

您还可以使用生成器作为迭代器:

while (my $num = $fib->next) {
    last if $num > 10**15;
    print "$_n";
}

$ fib-> next也可以写成$ fib->()。因为生成器仍然是随机访问,你可以$ fib-> reset()或$ fib-> index = 10;

如果您有任何问题,请与我们联系。

更新:

我已经发布了一个新版本的模块(0.80),使得更容易在生成器中使用迭代算法。这里是一个例子,紧密地反映了OP的例子:

use List::Gen '*';

sub fibonacci {
    my $limit   = 10**shift;
    my ($x,$y) = (0,1);

    While {$_ < $limit} gather {
        ($x,$y) = ($y,take($x) + $y)
    }
}

say for @{fibonacci 15};

如果你使用bigint;之前或在顶部的sub,你当然可以:

say for @{fibonacci 400}; # or more

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读