“我的”和“本地”之间的区别如何与符号引用相互作用?

时间:2012-08-30 04:25:32

标签: perl

以前我在“有效Perl编程”一书中阅读了相关内容,但并没有真正理解它。今天,我遇到了一个问题,如下面的代码。

my $vname = "a";
my @a = qw(1 2 3);
local @array = @$vname; 
foreach(@array) { print "$_\n"; };

它什么也没输出。然后我修改了这一行:

local @a = qw(1 2 3);  

用“本地”替换“我的”,然后现在就可以了。所以我想弄清楚它们之间的区别。

5 个答案:

答案 0 :(得分:14)

perldoc中有一个perlfaq7条目可以回答这个问题:

  

动态和词汇(静态)范围之间有什么区别?在local()my()之间?

     

local($x)可以保存全局变量$x的旧值   为子程序的持续时间分配一个新值   在从该子程序调用的其他函数中可见。这个完成了   在运行时,所以称为动态范围。 local()总会影响   全局变量,也称为包变量或动态变量。   my($x)创建一个仅在当前可见的新变量   子程序。这是在编译时完成的,所以它被称为词法或   静态范围。 my()始终影响私有变量,也称为私有变量   词汇变量或(不正确地)静态(缩放)变量。

     

例如:

sub visible {
    print "var has value $var\n";
}

sub dynamic {
    local $var = 'local';   # new temporary value for the still-global
    visible();              #   variable called $var
}

sub lexical {
    my $var = 'private';    # new private variable, $var
    visible();              # (invisible outside of sub scope)
}

$var = 'global';
visible();              # prints global
dynamic();              # prints local
lexical();              # prints global
     

请注意,“私人”的价值在任何时候都不会被打印出来。那是   因为$var仅在lexical()的块中具有该值   函数,它被调用的子程序隐藏。

     

总之,local()并不会使您认为是私人的,本地的   变量。它为全局变量提供临时值。我的()是什么   你是否想要私有变量。

     

参见Private Variables via my() in perlsub   和Temporary Values via local() in perlsub    令人难以忍受的细节。

答案 1 :(得分:9)

my创建一个新变量。它只能在声明它的词法范围内看到。

local创建一个在范围退出时恢复的全局变量的临时备份,但不会缩小其范围(它仍然可以在全局范围内看到)。它不会创建新变量。

您总是希望尽可能使用my,但是当您必须处理全局变量(例如local)时,$_是一个不错的近似值。

答案 2 :(得分:8)

Perl中有两种变量范围:

  • 全局变量:它们驻留在当前包中,可以从外部访问,并且可以具有“本地”值。该名称可以用作“存储”中的键,包变量哈希/符号表。
  • 词汇变量:它们位于当前范围内(大致由花括号分隔)。没有可以检查的符号表。

词法变量和全局变量不会干扰,可以有两个具有相同名称的不同变量。

大多数Perl变量魔法都发生在全局变量中。以下语法适用于全局变量:

our $var;
$::var;
$main::var;
${'var'};
local $var;

但不是my $var

所以我们可以写:

@::array = qw(a b c);
my @secondArray = @{array};

复制数组。我们还可以使用存储在变量中的名称查找数组:

@::array = qw(a b c);
my $name = "array";
my @secondArray = @{$name};

最后一行缩写为… = @$name

词法变量无法实现这一点,因为它们不存在于藏匿处。

local函数为当前作用域内以及在此作用域内调用的所有子作用域(“动态作用域”)中的全局变量(以及仅限全局变量)分配“本地”值。

最初(在Perl 4中)干扰变量名称和存储是模拟引用的唯一方法。这些用法现在大多已经过时了大约20年,因为有可用的参考资料(更安全的东西)。

答案 3 :(得分:2)

我想关注你使用它们时的主要案例:

  • my 应该是您希望仅限于特定区块的变量的“默认”。这应该是大部分时间
  • 如果您希望使用全局变量(特别是其中一个特殊变量),则
  • local 非常有用。例如

    local $/;                          # enable "slurp" mode
    local $_ = <$some_file_handle>;    # whole file now here
    

    使用本地可防止您的更改影响其他代码(包括您未编写的模块)

答案 4 :(得分:0)

在您的情况下,不同之处在于local解决了符号表中的变量而my没有。这很重要,因为如何使用它:

local @array = @$vname;

也就是说,您使用$vname作为symbolic reference(缺席no strict 'refs'的可疑实践告诉我们您知道自己在做什么)。 Quotha:

  

只有包变量(全局,即使是本地化)可见   象征性的参考。词汇变量(用my()声明)不在   符号表,因此对于这种机制是不可见的。

因此符号引用只能引用符号表中的变量。无论您将@a声明为my的词汇还是local的全球,@$vname只会引用@main::a。当你说

local @a = qw(1 2 3);

,您要为@main::a提供新值。当你说

my @a = qw(1 2 3);

,您正在创建一个新的词法变量@a并为其赋值,但保留@main::a未定义。当

local @array = @$vname;

然后访问@main::a的值,如果发现它未定义并将@array的值设置为它。

如果这一切看起来令人困惑,那就是因为它。这就是为什么强烈建议您使用strictwarnings(这可能会在这段代码上大量爆炸)并且不鼓励使用符号引用,除非您真的知道你是什么做的。