用my设置范围:默认情况下,perl中的变量是全局性的。使用my关键字可以将变量限制在封闭的程序块、条件、循环、子程序、eval语句、或者用do、require、use包含的文件中。my声明的变量具有“词汇意义的”范围,local声明的变量具有动态范围。
my与local的主要差异在:具有动态范围的变量在变量范围内调用的子程序是可以看见的。而具有词汇意义范围的变量并不是这样。使用子程序的结果就是用my声明的变量将完全局限于子程序内使用。为了用my声明数量值,以限制标量值的范围,需使用my $scalar。如果用my列出了多个元素,则列表必须出现在括号中。和my一起使用的所有元素都必须是合法的左值。
PS:只有数字字母标识符可以具有词汇范围,诸如$_这样的特殊内置元素必须使用local声明。 ----------------------------------------------------------------DEMO----------------------------------------------------------------------- sub printhem { my $inner=shift @_; print $inner; } printhem "Hello\n"; print $inner; PS:my仅适用于标量值、数组和哈希表 my $variable; my ($variable1,$variable2); my $variable=5; my @array=(1,2,3); my %hash; 声明为词汇范围的变量并没有限制在代码块中,相关的控制表达式也词汇范围的组成部分。 要求词汇范围的变量:把所用的全部变量都作为词汇范围的变量,可以使用附注:use strict 'vars'。这样,将从那个点开始到封闭程序块或者范围末尾之间对变量的任何引用,都必须引用专门声明的词汇变量,或者必须用它的包名称来限定。local创建临时变量:local创建动态范围变量,建立全局变量的临时副本,并使用这个临时副本,直至超出范围(那时,将恢复全局变量的值)必须使用local的地方:创建类似$_特殊变量的局部副本、修改数组或哈希表中的一个元素、局部使用文件句柄和perl格式。
PS:local并不会创建变量,只创建全局变量的副本(而且保留全局变量的值,以供本地副本超出范围时候恢复)使用local将建立所列变量的副本,并使它们局限于封闭的程序块、eval语句、do语句、从那个块内调用的任何子程序。
-----------------------------------------------------Demo----------------------------------------------------------- sub printifok { local $local_value=$V_value; if($local_value>10){ print "V_value is $V_value.\n"; }else{ print "V_value is too small.\n"; } } $V_value=10; printifok; $V_value=12; printifok; 确定my和local之间的差别:my创建了一个新变量,local将保存现存变量的副本。local是运行期间的结构,而不是编译期间的结构,用local对全局变量你的改动在通过子程序调用离开局部范围时任然有效。通常情况下,应该使用my,而不是local。my的执行速度快,而且没有全局副作用。然而,注意,必须使勇local来局部化任何以$开头的特殊变量。用my声明的变量存储在专用符号表中,而不是作为整个包的符号表的组成部分。 用our设置变量:处理全局变量。our声明方法声明了变量在封闭的程序块、文件或者eval语句内是合法的全局变量。our不会创建任何局部变量。 ----------------------------------------------------Demo----------------------------------------------- package package1; $value_1=5; package package2; print "\$value_1 =" .$value_1; package package1; our $value_1; $value_1=5; package package2; print "\$value_1 =" .$value_1."\n"; 创建永久(静态)变量:有时候希望让子程序中的变量在两次调用子程序之间保留它的值,然而,如果用my或者local在子程序中声明变量,这些变量将在每次进入子程序的时候重置。 --------------------------------------Demo-------------------------------------- sub incrementcount { my $count; return ++$count; } print incrementcount ."\n"; print incrementcount ."\n"; print incrementcount ."\n"; print incrementcount ."\n"; 如果$count成为静态变量可以解决这个问题,但perl不直接支持静态变量,默认情况下,全局变量是静态的,但用my声明的子程序变量不是静态的。词汇变量只要处于范围之内就不会重置。将my声明放在子程序外进行,然后将代码(声明和子程序)都放在括号内,这使得它的层次和对子程序的调用的层次相同: { my $count; sub incrementcount { return ++$count; } } print incrementcount ."\n"; print incrementcount ."\n"; print incrementcount ."\n"; print incrementcount ."\n"; 也可以将所有内容放在BEGIN块中,这个块将在程序加载的时候运行: sub BEGIN { my $count; sub incrementcount { return ++$count; } print incrementcount ."\n"; print incrementcount ."\n"; print incrementcount ."\n"; print incrementcount ."\n"; }得到子程序的名称和caller:caller函数返回当前子程序上下文的信息。一般情况下,可以这样使用caller:
caller EXPR caller 在标量上下文中,如果在子程序使用,则返回主调代码包的名称,或者返回eval或者requore,否则返回不确定的值。 在表上下文中,这个函数像这样返回列表: ($package,$filename,$line)=caller; 如果包含了EXPR,则caller返回其他信息,调试人员可以用这些信息打印堆栈跟踪记录。EXPR的值说明在当前堆栈架之前有多少堆栈框架需要返回(也就是子程序调用)。 ($package,$filename,$line,$subroutine,$hasargs,$wantarray,$evaltext,$is_require)=caller($s); ----------------------------------------------------Demo-------------------------------------- sub addem_1 { ($value_1,$value_2) = @_; $value_1+$value_2; print join(" ,",caller); } $value_3=addem_1(2,2); 递归调用子程序: sub factorial { my $value=shift (@_); return $value== 1? $value:$value * factorial ($value-1); } $result_1=factorial(6); print $result_1."\n"; 在递归的情况下,需要my来局部化变量 嵌套子程序:perl支持嵌套子程序,可以在子程序的内部嵌套子程序。 ----------------------------------Demo---------------------------------------- sub outer { my $s="Inside the inner subroutine.\n"; sub inner { my $s2=$s; print $s2; } inner(); } outer(); 内联函数:如果函数的原型是(),既没有任何参数,则该函数在perl便以其中就是内联的。这样的函数必须由常量或者词汇范围内的标量构成。不能用&或者do引用。 覆盖内置子程序:当覆盖子程序时,就为它提供了一个新定义。可以覆盖子程序,包括内置在perl中的函数,但仅能覆盖从模块中导入的子程序。 可以使用subs附注用导入语法预先声明子程序,可以使用那些名称来覆盖内置函数。 ---------------------------覆盖内置子程序例子----------------------------------------- sub subs 'exit'; sub exit { print "Do you really want to exit?"; $answer= <>; if($answer =~ m/^y/i){ CORE::exit; } } while(1){ exit; }; 重新定义子程序: { #----------------------创建子程序sub_1----------------------- my $text=shift; sub sub_1 { $text=shift; print "$text there!\n"; } #----------------------创建子程序sub_2----------------------- sub sub_2 { $text=shift; print "$text everyone!\n"; } #-----调用sub_1,重新定义它,使得它引用sub_2,并再次调用它------- sub_1("Hello"); *sub_1=\&sub_2; sub_1("Hello"); } WEL测试 认证博客专家 软件测试 性能测试 接口测试 一线的测试工作人员。喜欢专研并应用新的技术,用于提升测试效率。擅长:测试新人培训、测试进阶、接口测试、性能测试、问题定位、自动化、数据测试、渗透测试! 如果对测试感兴趣或者遇到一些难题,可以加我微信:Wel_Test,加时填好备注!