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

Perl专题之函数(二)函数参数与返回值

发布时间:2020-12-16 00:05:14 所属栏目:大数据 来源:网络整理
导读:2. ? ? ? 函数的参数和返回值 2.1.基本用法 Perl中函数所有的参数作为一个标量列表传入,如果想函数传入数组或者散列,那么传入的数组或者散列的每个元素都会被放入这个标量列表中,在函数内部可以使用数组@_来获取传入的这些参数。注意,@_是一个本地变量,

2. ? ? ? 函数的参数和返回值

2.1.基本用法

Perl中函数所有的参数作为一个标量列表传入,如果想函数传入数组或者散列,那么传入的数组或者散列的每个元素都会被放入这个标量列表中,在函数内部可以使用数组@_来获取传入的这些参数。注意,@_是一个本地变量,它的每一个元素都是实际参数的一个引用,所以,如果修改实际参数对应的@_中的元素就会修改实际参数,这种情况又一个例外,那就是散列。当传入一个散列作为参数时,散列的键是不会改变的,只能修改散列的值。

我们做如下的测试脚本:

=pod

脚本名称:04_input_params.pl

脚本目的:该脚本用来测试函数参数数组@_的语法

作 ? 者:加水石灰

=cut

sub test_input_params{

? print "@_n";

? $_[1]="Unkown";

? $_[0]="Unkown";

}

my@params=("Linux","Perl","Oracle");

my%params=(OS=>"Linux",LANGUAGE=>"Perl",DATABASE=>"Oracle");

my $param1="Linux";

my $param2="Perl";

my $param3="Oracle";

test_input_params @params;

test_input_params %params;

test_input_params$param1,$param2,$param3;

test_input_params @params;

test_input_params %params;

test_input_params$param1,$param3


测试脚本的输出结果如下:

Linux PerlOracle

DATABASE OracleLANGUAGE Perl OS Linux

Linux PerlOracle

Unkown UnkownOracle

DATABASE UnkownLANGUAGE Perl OS Linux

Unkown UnkownOracle

从结果可以看出所有的传入参数都被解析成了列表,放入了@_数组当中。代码中修改@_数组的第一个值和第二个值为Unkown,第二次调用时除了散列的键之外所有的参数就已经发生改变。

如果没有显式的return语句,那么Perl函数的返回值就是函数体中最后一个表达式的值。不管是显式的调用return,还是隐式返回最后一个表达式的值,其执行环境都依赖于外部的该函数被调用的环境。

我们做测试脚本如下:

=pod

脚本名称:05_return_values.pl

脚本目的:该脚本用来测试函数返回值数组

者:加水石灰

=cut

sub test_return_values{

? ?my@params=("Linux","Oracle");

? ?my%params=(OS=>"Linux",DATABASE=>"Oracle");

? ?my$param="Linux";

? ?if($_[0] eq"ARRAYALL"){

? ? ? ?return@params,%params,$param;

? ?}elsif($_[0] eq"HASHALL"){

? ? ? ?return%params,$param,@params;

? ?}elsif($_[0] eq"SCALARALL"){

? ? ? ?return$param,@params,%params;

? ?}elsif($_[0] eq"ARRAY"){

? ? ? ?@params;

? ?}elsif($_[0] eq"HASH"){

? ? ? ?%params;

? ?}elsif($_[0] eq"SCALAR"){

? ? ? ?$param;

? ?}

}

my @ret = test_return_values("ARRAYALL");

print "ARRAYALL:@retn";

print"ARRAYALL:".test_return_values("ARRAYALL")."nn";

@ret = test_return_values("HASHALL");

print "HASHALL:@retn";

print"HASHALL:".test_return_values("HASHALL")."nn";

@ret = test_return_values("SCALARALL");

print "SCALARALL:@retn";

print"SCALARALL:".test_return_values("SCALARALL")."nn";

@ret = test_return_values("ARRAY");

print "ARRAY:@retn";

print "ARRAY:".test_return_values("ARRAY")."nn";

@ret = test_return_values("HASH");

print "HASH:@retn";

print"HASH:".test_return_values("HASH")."nn";

@ret = test_return_values("SCALAR");

print "SCALAR:@retn";

print"ARRAYALL:".test_return_values("SCALAR")."nn";

上面脚本的输出如下:

ARRAYALL:LinuxPerl Oracle DATABASE Oracle LANGUAGE Perl OS Linux Linux

ARRAYALL:Linux

HASHALL:DATABASEOracle LANGUAGE Perl OS Linux Linux Linux Perl Oracle

HASHALL:3

SCALARALL:LinuxLinux Perl Oracle DATABASE Oracle LANGUAGE Perl OS Linux

SCALARALL:2/8

ARRAY:LinuxPerl Oracle

ARRAY:3

HASH:DATABASEOracle LANGUAGE Perl OS Linux

HASH:2/8

SCALAR:Linux

ARRAYALL:Linux


从上面的脚本可以看出,函数返回的是return语句或者最后一个表达式的值,return语句或者最后一个表达式的执行环境和函数被调用的环境一致。比如传入HASH参数是,列表环境下返回的是一个平面化的列表,而标量环境下返回的是2/8,即HASH内部占用的块数和一共分配的块数。

上文提到函数的传入参数是引用传递,我们可以通过吧@_赋值给本地变量来避免引用传递带来的麻烦。

2.2.命名参数与默认参数

Perl函数是不支持命名参数,只支持位置参数。命名参数可以通过以下几步来实现:

1、首先函数体内将@_数组赋值给一个散列。

2、函数调用时采用(参数名,参数值)配对的方式进行调用。

我们做如下测试代码:

=pod

脚本名称:06_named_params.pl

脚本目的:本脚本用来展示传入参数的经常用法

作 ? 者:加水石灰

=cut

sub test_named_params{

? my %params=@_;

? print $params{"PARAM1"}."n";

? print $params{"PARAM2"}."n";

}

test_named_params(PARAM1=>"PARAMETER1",PARAM2=>"PARAMETER2");

上面测试代码的输出如下:

PARAMETER1

PARAMETER2

这种方式除了有普通命名函数的优点外(可惜,使用起来要多敲好多字母),还不受传入参数顺序的限制。我们调用函数时只需要保证参数名正确即可。

这种方式还带来另一种好处,即可以实现默认参数。

我们写如下测试脚本:

=pod

脚本名称:07_default_params.pl

脚本目的:本脚本用来展示默认参数的用法

作 ? 者:加水石灰

=cut

sub test_default_params{

? my %params=(

? ? ? ? ? ?PARAM1=>"DEFAULT",

? ? ? ? ? ?PARAM2=>"DEFAULT",

? ? ? ? ? ?@_

? );

? print $params{"PARAM1"}."n";

? print $params{"PARAM2"}."n";

}

test_default_params(PARAM1=>"PARAMETER1",PARAM2=>"PARAMETER2");

print "n";

test_default_params(PARAM1=>"PARAMETER1");

print "n";

test_default_params(PARAM2=>"PARAMETER2");

print "n";

test_default_params()

上述代码的测试结果如下:

PARAMETER1

PARAMETER2

PARAMETER1

DEFAULT

DEFAULT

PARAMETER2

DEFAULT

DEFAULT

从测试结果可以看出通过上述的代码可以实现默认参数,这种方式的好处是默认参数可以在任何位置,没有C语言中默认参数必须在参数列表最后的限制。

2.3.静态变量

Perl中实现静态变量有两种方式:闭环和state关键字。我们做如下代码如下:

=pod

脚本名称:08_static_variables.pl

脚本目的:本脚本用来展示静态变量的实现方式

者:加水石灰

=cut

{

? ?my$static_values=1;

? ?subtest_static_values{

? ? ? $static_values++;

? ? ? ?print$static_values."n";

? ?}

}

test_static_values;

test_static_values;

test_static_values;

test_static_values;

use feature 'state';

sub test_static_values2{

? ?state$static_values = 10;

? $static_values++;

? ?print$static_values."n";

}

test_static_values2;

test_static_values2;

test_static_values2;

test_static_values2

测试脚本测试如下:

2

3

4

5

11

12

13

14

需要注意的一点就是使用state函数时需要提前声明:

use feature 'state';

2.4.传递引用

在2.1节中提到,所有传入Perl子函数中的参数和返回值都会被平板化为一个列表。所以,传入Perl子函数或者从Perl子函数中返回的数组或者散列就会被与其它传入参数/返回值糅合在一起,而失去他们原有的结构。如果希望保留各个参数/返回值本来的结构,我们可以通过显式传递引用的方式来实现,即将数组或者散列的引用(一个标量)而不是其本身传入函数中或者从函数中返回。

我们做如下测试代码

=pod

脚本名称:09_pass_reference.pl

脚本目的:本脚本用来展示用传递引用的方式保留传入参数原有的结构

作 ? 者:加水石灰

=cut

sub test_pass_reference{

? my $param1 = $_[0];

? my $param2 = $_[1];

? my @ret1 = map {$_*$_} @$param1;

? my @ret2 = map {$_+$_} @$param2;

? return (@ret1,@ret2);

}

my @param1=(1,3,5,7,9);

my @param2=(2,4,6,8,10);

my($ret1,$ret2)=test_pass_reference(@param1,@param2);

print ("@$ret1n");

print ("@$ret2n")

上述代码的输出为:

1 9 25 49 81

4 8 12 16 20

由结果可以看出,通过引用传递的方式是可以保留传入参数和返回值原有结构的。

(编辑:李大同)

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

    推荐文章
      热点阅读