设为首页 收藏本站
查看: 876|回复: 0

[经验分享] Perl专题之函数(二)函数参数与返回值

[复制链接]

尚未签到

发表于 2018-8-31 06:14:38 | 显示全部楼层 |阅读模式
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,$param2,$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","Perl","Oracle");
      my%params=(OS=>"Linux",LANGUAGE=>"Perl",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:@ret\n";
  print"ARRAYALL:".test_return_values("ARRAYALL")."\n\n";
  
  @ret = test_return_values("HASHALL");
  print "HASHALL:@ret\n";
  print"HASHALL:".test_return_values("HASHALL")."\n\n";
  
  @ret = test_return_values("SCALARALL");
  print "SCALARALL:@ret\n";
  print"SCALARALL:".test_return_values("SCALARALL")."\n\n";
  
  @ret = test_return_values("ARRAY");
  print "ARRAY:@ret\n";
  print "ARRAY:".test_return_values("ARRAY")."\n\n";
  
  @ret = test_return_values("HASH");
  print "HASH:@ret\n";
  print"HASH:".test_return_values("HASH")."\n\n";
  
  @ret = test_return_values("SCALAR");
  print "SCALAR:@ret\n";
  print"ARRAYALL:".test_return_values("SCALAR")."\n\n";
  
  上面脚本的输出如下:
  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 ("@$ret1\n");
  print ("@$ret2\n")
  上述代码的输出为:
  1 9 25 49 81
  4 8 12 16 20
  由结果可以看出,通过引用传递的方式是可以保留传入参数和返回值原有结构的。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-559009-1-1.html 上篇帖子: perl mojo安装时curl提示没有证书的解决方法 下篇帖子: Perl专题之函数(三)函数原型
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表