Jer*_*que 54
简短的回答是my在词法范围内local将变量标记为私有,并在动态范围内将变量标记为私有.
它更容易理解my,因为它创建了通常意义上的局部变量.创建了一个新变量,它只能在封闭的词块中访问,该词块通常用花括号标记.大括号规则有一些例外,例如:
foreach my $x (@foo) { print "$x\n"; }
Run Code Online (Sandbox Code Playgroud)
但那只是Perl做你的意思.通常你有这样的事情:
sub Foo {
my $x = shift;
print "$x\n";
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,$x子程序是私有的,其范围由花括号括起来.需要注意的local是,my与之对比的是,变量的范围是根据代码定义的,因为它是在文件中编写的.这是一个编译时的现象.
要理解local,您需要根据程序运行时的调用堆栈进行思考.当一个变量是local,它从local语句为堆栈下面的所有内容执行的点重新定义,直到你将堆栈返回给包含该变量的块的调用者local.
这可能会让人感到困惑,因此请考虑以下示例.
sub foo { print "$x\n"; }
sub bar { local $x; $x = 2; foo(); }
$x = 1;
foo(); # prints '1'
bar(); # prints '2' because $x was localed in bar
foo(); # prints '1' again because local from foo is no longer in effect
Run Code Online (Sandbox Code Playgroud)
当foo第一次调用时,它看到其全局值为$x1.当bar调用并local $x运行时,重新定义$x堆栈上的全局值.现在foo调用时bar,它会看到2的新值$x.到目前为止,这并不是很特别,因为没有调用就会发生同样的事情local.神奇的是,当bar返回时,我们退出由之创建的动态范围,local $x并且之前的全局$x返回范围.因此,对于最后的召唤foo,$x是1.
您几乎总是想要使用my,因为它为您提供了您正在寻找的局部变量.一旦进入一个蓝色的月亮,local真的很方便做酷事.
J.J*_*.J. 37
动态范围.这是一个很好的概念.很多人不使用它,也不了解它.
基本上认为my创建和锚定变量到{},AKA范围的一个块.
my $foo if (true); # $foo lives and dies within the if statement.
Run Code Online (Sandbox Code Playgroud)
所以my变量就是你习惯的.而对于动态范围,$ var可以在任何地方声明并在任何地方使用.因此,local基本上暂停使用该全局变量,并使用"本地值"来处理它.因此local,为临时变量创建临时范围.
$var = 4;
print $var, "\n";
&hello;
print $var, "\n";
# subroutines
sub hello {
local $var = 10;
print $var, "\n";
&gogo; # calling subroutine gogo
print $var, "\n";
}
sub gogo {
$var ++;
}
Run Code Online (Sandbox Code Playgroud)
这应该打印:
4
10
11
4
Run Code Online (Sandbox Code Playgroud)
Dre*_*ens 19
引用学习Perl:
但是当地人的名字不好,或者至少是误导性地命名.我们的朋友Chip Salzenberg说,如果他有机会回到1986年的时间机器并给Larry一条建议,他会告诉Larry用"save"这个名称给当地人打电话.[14] 那是因为local实际上会将给定的全局变量的值保存起来,因此稍后会自动恢复到全局变量.(这是正确的:这些所谓的"本地"变量实际上是全局变量!)这个保存和恢复机制与我们已经在foreach循环的控制变量和@_中已经看过两次相同.子程序参数数组.
因此,local保存全局变量的当前值,然后将其设置为某种形式的空值.你会经常看到它曾经用来啜饮整个文件,而不是只引出一条线:
my $file_content;
{
local $/;
open IN, "foo.txt";
$file_content = <IN>;
}
Run Code Online (Sandbox Code Playgroud)
调用local $/将输入记录分隔符(Perl停止读取"行"的值)设置为空值,导致太空船操作员读取整个文件,因此它永远不会到达输入记录分隔符.
Ari*_*zis 16
我无法相信没有人与Mark Jason Dominus关于此事的详尽论述有关:
然后,如果你想知道什么local是好事,那么
七个有用的用途local
http://perldoc.perl.org/perlsub.html#Private-Variables-via-my()
与本地运算符创建的动态变量不同,使用my声明的词法变量完全隐藏在外部世界中,包括任何被调用的子例程.如果它是从自身或其他地方调用的相同子例程,则这是真的 - 每个调用都有自己的副本.
http://perldoc.perl.org/perlsub.html#Temporary-Values-via-local()
本地修改其列出的变量为封闭块的"本地",eval或do FILE - 以及从该块中调用的任何子例程.本地只是为全局(意味着包)变量提供临时值.它不会创建局部变量.这称为动态范围.词法范围是用我的完成的,它更像是C的自动声明.
我不认为这根本不清楚,除了说"封闭块的本地"之外,它意味着当块退出时原始值被恢复.
谷歌真的适合你这个:http://www.perlmonks.org/?node_id = 94007
从链接:
快速摘要:'my'创建一个新变量,'local'暂时修改变量的值.
即,'local' 临时更改变量的值,但仅 在其存在的范围内.
一般使用我的,它更快,并没有做任何奇怪的事情.
来自man perlsub:
与本地运算符创建的动态变量不同,使用my声明的词法变量完全隐藏在外部世界中,包括任何被调用的子例程.
因此,过度简化,my使您的变量仅在声明的位置可见.local使它在调用堆栈中也可见.您通常希望使用my而不是local.
你的困惑是可以理解的。词法作用域相当容易理解,但动态作用域是一个不寻常的概念。由于历史原因,名称my和local有些不准确(或至少不直观)使情况变得更糟。
my声明一个词法变量——从声明点到封闭块(或文件)末尾都是可见的。它完全独立于程序其余部分中具有相同名称的任何其他变量。它是该块私有的。
local另一方面,声明对全局变量值的临时更改。更改在封闭范围的末尾结束,但变量(全局变量)在程序中的任何位置都可见。
根据经验,使用my声明您自己的变量并local控制 Perl 内置变量更改的影响。
有关更全面的描述,请参阅 Mark Jason Dominus 的文章Coping with Scoping。
local 是一种较旧的本地化方法,从 Perl 仅具有动态作用域的时代开始。词法作用域对于程序员来说更加自然,并且在许多情况下更加安全。我的变量属于声明它们的范围(块、包或文件)。
相反,局部变量实际上属于全局名称空间。如果你用local引用变量$x,你实际上引用的是$main::x,它是一个全局变量。与它的名称所暗示的相反,所有 local 所做的都是将新值推送到 $main::x 的值堆栈上,直到该块结束,此时旧值将被恢复。这本身就是一个有用的功能,但由于多种原因,它并不是使用局部变量的好方法(想想当你有线程时会发生什么!并想想当你调用一个真正想要使用全局变量的例程时会发生什么)您已本地化!)。然而,在 Perl 5 之前的糟糕日子里,这是让变量看起来像局部变量的唯一方法。我们仍然坚持它。