以前我在“有效Perl编程”一书中阅读了相关内容,但并没有真正理解它。今天,我遇到了一个问题,如下面的代码。
my $vname = "a";
my @a = qw(1 2 3);
local @array = @$vname;
foreach(@array) { print "$_\n"; };
它什么也没输出。然后我修改了这一行:
local @a = qw(1 2 3);
用“本地”替换“我的”,然后现在就可以了。所以我想弄清楚它们之间的区别。
答案 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)
我想关注你使用它们时的主要案例:
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
的值设置为它。
如果这一切看起来令人困惑,那就是因为它。这就是为什么强烈建议您使用strict
和warnings
(这可能会在这段代码上大量爆炸)并且不鼓励使用符号引用,除非您真的知道你是什么做的。