Perl 变量魔法

先来看一段 Perl 脚本:

sub showVars {
 
    
my $name = "first";
    
print    $name"\t at " . \$name . "\n";
    
for(my $i = 0; $i < 2; $i++) {
        
my $name = "loop_" . $i;
        
if (1 < 3) {
            
print    $name"\t at " . \$name . "\n";
            
my $name = "if_A";
            
print    $name"\t at " . \$name . "\n";
            
{
                
my $name = "blank";
                
print    $name"\t at " . \$name . "\n";
            
}
            
print    $name"\t at " . \$name . "\n";
        
}
        
if (1 < 4) {
            
print    $name"\t at " . \$name . "\n";
            
my $name = "if_B";
            
print    $name"\t at " . \$name . "\n";
        
}
        
print    $name"\t at " . \$name . "\n";
    
}
    
print    $name"\t at " . \$name . "\n";
}
 
sub showVars_2 {
 
    
my $name = "first";
    
print    $name"\t at " . \$name . "\n";
    
for(my $i = 0; $i < 2; $i++) {
        
$name = "loop_" . $i;
        
if (1 < 3) {
            
print    $name"\t at " . \$name . "\n";
            
$name = "if_A";
            
print    $name"\t at " . \$name . "\n";
            
{
                
$name = "blank";
                
print    $name"\t at " . \$name . "\n";
            
}
            
print    $name"\t at " . \$name . "\n";
        
}
        
if (1 < 4) {
            
print    $name"\t at " . \$name . "\n";
            
$name = "if_B";
            
print    $name"\t at " . \$name . "\n";
        
}
        
print    $name"\t at " . \$name . "\n";
    
}
    
print    $name"\t at " . \$name . "\n";
}
 
showVars();
print    "--------------\n";
showVars_2();

这里面有 2 个函数,两者之间的区别,就是变量的定义方式不同。

第一个函数,多次使用 my 声明变量。Perl 会在每一个局部区域内,比如说大括号 {} 内,实现一个命名空间。
也就是说,在不同的代码段,相同的变量名,实际上指向了不同的内存地址。
第一个函数体内,首先声明了一个变量 $name,他的作用域是整个函数,但在 for 循环体内,又用 my 声明了 $name 变量,因为 for 是一个封闭的结构,在 {} 里面就可以产生一个新的命名空间,此时 $name 指向了一个新的内存地址。这一点可以在后面的输出结果中看到。

由此,引发一个值得思考的问题:
如果在循环体内部用 my 去声明变量,那么循环执行多少次,就会有多少个变量的副本,这会浪费很多内存空间。
这一点是跟其他类 C 语言是有很大区别的。
所以,如果你要想利用 Perl 的命名空间,那么只要多注意代码段的作用范围,编程的时候能感受到 Perl 十分强大的便利性。
需要注意的,就是避免在循环体中使用 my 声明,浪费内存空间不说,还会影响程序的性能。

说了半天,还是看一看实际的结果吧:

$ perl show_vars.pl
first    at SCALAR(0x182fb10)
loop_0   at SCALAR(0x182fbb8)
if_A     at SCALAR(0x182fc24)
blank    at SCALAR(0x182fc84)
if_A     at SCALAR(0x182fc24)
loop_0   at SCALAR(0x182fbb8)
if_B     at SCALAR(0x182fd5c)
loop_0   at SCALAR(0x182fbb8)
loop_1   at SCALAR(0x182fd5c)
if_A     at SCALAR(0x182fc84)
blank    at SCALAR(0x276164)
if_A     at SCALAR(0x182fc84)
loop_1   at SCALAR(0x182fd5c)
if_B     at SCALAR(0x182fc24)
loop_1   at SCALAR(0x182fd5c)
first    at SCALAR(0x182fb10)
--------------
first    at SCALAR(0x182fe88)
loop_0   at SCALAR(0x182fe88)
if_A     at SCALAR(0x182fe88)
blank    at SCALAR(0x182fe88)
blank    at SCALAR(0x182fe88)
blank    at SCALAR(0x182fe88)
if_B     at SCALAR(0x182fe88)
if_B     at SCALAR(0x182fe88)
loop_1   at SCALAR(0x182fe88)
if_A     at SCALAR(0x182fe88)
blank    at SCALAR(0x182fe88)
blank    at SCALAR(0x182fe88)
blank    at SCALAR(0x182fe88)
if_B     at SCALAR(0x182fe88)
if_B     at SCALAR(0x182fe88)
if_B     at SCALAR(0x182fe88)

Post a comment

Google

Google
LAMP-Linux-redhat LAMP-Apache LAMP-MySQL LAMP-Php Leakon-Wiki Leakon-BBS XueBaoBao Xyoyou