our,my和local都是用来声明或者定义变量的关键字,他们之间的关系一度令我感到迷惑,现在就一步步的阐述三者之间的区别。一个简单的总结性描述如下:
-
our: 定义或者声明一个全局变量,在当前的包环境下。
-
my: 定义一个新的、局部范围(块或者文件)有效的变量。
-
local: 重新定义局部范围有效的变量,主要用于屏蔽同名的全局变量。
从上面的大致描述上可以看出,my变量才是真正的局部变量,而local变量更像是局部作用的全局变量。根据官方的perl文档(5.20),相比于local,应该使用my,因为my更加快速而且安全。一些例外的情况包括,全局符号变量,全局文件句柄和范式(format)等的修改和使用,也就是说,当在被调用的函数中也需要访问这些变量时,使用local。从这个角度来看,my和local虽然都是局部的变量,但是my是静态的(受限于源文件中的物理位置),local是动态的。
our 和 my 的区别
在分析our,my和local三者的关系之前,首先要弄清楚our和my之间的区别。
从perl5开始,my被用来声明
-
非package变量,它们是
-
私有的
-
新的
-
非全局的
-
独立于包的,不能通过包前缀方式访问,如$package_name::variable
our 变量
-
包变量
-
全局变量
-
非私有
-
不一定是重新建立的,有时仅提示编译器这个是已经存在的全局变量
-
能通过包前缀方式访问,如$package_name::variable
这里是一段示例代码。
-
use strict;
-
-
for (1 ..2){
-
# Both variables are lexically scoped to the block.
-
our ($o); # Belongs to 'main' package.
-
my ($m); # Does not belong to a package.
-
-
# The variables differ with respect to newness.
-
$o ++;
-
$m ++;
-
print __PACKAGE__, " >> o=$o m=$m\n"; # $m is always 1.
-
-
# The package has changed, but we still have direct,
-
# unqualified access to both variables, because the
-
# lexical scope has not changed.
-
package Fubb;
-
print __PACKAGE__, " >> o=$o m=$m\n";
-
}
-
-
# The our() and my() variables differ with respect to privacy.
-
# We can still access the variable declared with our(), provided
-
# that we fully qualify its name, but the variable declared
-
# with my() is unavailable.
-
print __PACKAGE__, " >> main::o=$main::o\n"; # 5
-
print __PACKAGE__, " >> main::m=$main::m\n"; # Undefined.
-
-
# Attempts to access the variables directly won
my 和 local 的区别
首先看local的情况
-
$a = 3.14159;
-
{
-
local $a = 3;
-
print "In block, \$a = $a\n";
-
print "In block, \$::a = $::a\n";
-
}
-
print "Outside block, \$a = $a\n";
-
print "Outside block, \$::a = $::a\n";
-
-
# This outputs
-
In block, $a = 3
-
In block, $::a = 3
-
Outside block, $a = 3.14159
-
Outside block, $::a = 3.14159
local 临时的改变了变量的值,仅仅在所处的区域内。它改变了全局同名变量的值。
而,my 创建了仅在所处区域内有效的,一个符号表中不存在的变量。它对全局同名变量没有任何影响。
-
$a = 3.14159;
-
{
-
my $a = 3;
-
print "In block, \$a = $a\n";
-
print "In block, \$::a = $::a\n";
-
}
-
print "Outside block, \$a = $a\n";
-
print "Outside block, \$::a = $::a\n";
-
-
# This outputs
-
In block, $a = 3
-
In block, $::a = 3.14159
-
Outside block, $a = 3.14159
-
Outside block, $::a = 3.14159
从typeglob(类型团)角度看my和local
其实对于 my 和 local ,主要还是和 typeglob 有关系。对于一个 perl 中的变量,都有一个 符号表 与之对应,比如有
-
$perl = 'a';
-
@perl = qw / a b c d /;
-
%perl = ...;
-
sub perl {};
-
open(perl,...);
看起来其为同名,不同类型的各种符号,但在perl中,他们都是存放在一个的符号表中的同一个表项中的,都是在名为 perl 的表项。然后通过一个 typeglob 的数据结构来来把各种值分开,typeglob 也就是 *perl
我们不妨做个实验
-
$a = 'a';@a = qw / a b c /;
-
print "a is ",$a,"\t",@a,"\n";
-
print "b is ",$b,"\t",@b,"\n";
-
*b=*a;
-
print "now b is ",$b,"\t",@b,"\n";
当我们执行完了 *b=*a;也就是typeglob赋值操作以后,等于说在这个代码段中又建立了一个 符号表项 ,也就是 b,那么这个符号表项所指向的 typeglob 和 a 一样。这样,等于说就同时建立了一个和a关联的b的变量,包括 $b,@b
对于local操作,其实是在这个代码段前,先把此 typeglob 中的各个项的值保存,然后在进行对这些变量的操作和运算,这样的话在该代码段结束前,这些变量“看起来”好象没什么变化,等到该代码段结束了,local的变量就会取出原来备份的值,在替换了现有的值。
而 my 呢?
my 并没有用到 typeglob 和 符号表,my 是在每个代码段都建立一个特殊的地方来专门存储这些变量,而且my的变量中没有了 typeglob 的概念,也就是说 my 中的 $a , @a 都是按一定的顺序存放到一个内存区中的,不会出现 *b=*a 的情况了。而在代码段结束的时候,只要这些变量的引用记数为0,就释放这些变量。
阅读(7341) | 评论(0) | 转发(0) |