Perl 中的 my 和 local 有什么区别?
我看到它们都用在我正在尝试调试的脚本中,但文献还不清楚。 有人能为我揭开这个神秘面纱吗?
I am seeing both of them used in this script I am trying to debug and the literature is just not clear. Can someone demystify this for me?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
来自
man perlsub
:与本地运算符创建的动态变量不同,用 my 声明的词法变量完全对外界隐藏,包括任何调用的子例程。
因此,过于简单化,< code>my 使您的变量仅在声明的地方可见。
local
也使其在调用堆栈中可见。 您通常需要使用my
而不是local
。From
man perlsub
:Unlike dynamic variables created by the local operator, lexical variables declared with my are totally hidden from the outside world, including any called subroutines.
So, oversimplifying,
my
makes your variable visible only where it's declared.local
makes it visible down the call stack too. You will usually want to usemy
instead oflocal
.你的困惑是可以理解的。 词法作用域相当容易理解,但动态作用域是一个不寻常的概念。 由于历史原因,名称
my
和local
有点不准确(或至少不直观),这使得情况变得更糟。my
声明一个词法变量——从声明点到封闭块(或文件)末尾都是可见的。 它完全独立于程序其余部分中具有相同名称的任何其他变量。 它是该块私有的。另一方面,
local
声明对全局变量值的临时更改。 更改在封闭范围的末尾结束,但变量(全局变量)在程序中的任何位置都可见。根据经验,使用
my
声明您自己的变量,并使用local
来控制 Perl 内置变量更改的影响。有关更全面的描述,请参阅 Mark Jason Dominus 的文章应对范围界定。
Your confusion is understandable. Lexical scoping is fairly easy to understand but dynamic scoping is an unusual concept. The situation is made worse by the names
my
andlocal
being somewhat inaccurate (or at least unintuitive) for historical reasons.my
declares a lexical variable -- one that is visible from the point of declaration until the end of the enclosing block (or file). It is completely independent from any other variables with the same name in the rest of the program. It is private to that block.local
, on the other hand, declares a temporary change to the value of a global variable. The change ends at the end of the enclosing scope, but the variable -- being global -- is visible anywhere in the program.As a rule of thumb, use
my
to declare your own variables andlocal
to control the impact of changes to Perl's built-in variables.For a more thorough description see Mark Jason Dominus' article Coping with Scoping.
上面的脚本打印 6。
但是如果我们将 local 更改为 my,它将打印 5。
这就是区别。 简单的。
The above script prints 6.
But if we change local to my it will print 5.
This is the difference. Simple.
仅当您在子例程中调用子例程时,它才会有所不同,例如:
它不打印任何内容,因为
$x
受 bar 的{}
限制,并且对调用的子例程不可见,例如:它将打印 2,因为局部变量对被调用的子例程可见。
It will differ only when you have a subroutine called within a subroutine, for example:
It prints nothing as
$x
is limited by{}
of bar and not visible to called subroutines, for example:It will print 2 as local variables are visible to called subroutines.
查看以下代码及其输出以了解其中的差异。
输出是:
Look at the following code and its output to understand the difference.
Output is :
local 是一种较旧的本地化方法,从 Perl 仅具有动态作用域的时代开始。 词法作用域对于程序员来说更加自然,并且在许多情况下更加安全。 我的变量属于声明它们的范围(块、包或文件)。
相反,局部变量实际上属于全局名称空间。 如果你用local引用变量$x,你实际上引用的是$main::x,它是一个全局变量。 与它的名称所暗示的相反,所有 local 所做的都是将新值推送到 $main::x 的值堆栈上,直到该块结束,此时旧值将被恢复。 这本身就是一个有用的功能,但由于多种原因,它并不是使用局部变量的好方法(想想当你有线程时会发生什么!并想想当你调用一个真正想要使用全局变量的例程时会发生什么)您已本地化!)。 然而,在 Perl 5 之前的糟糕日子里,这是让变量看起来像局部变量的唯一方法。我们仍然坚持它。
local is an older method of localization, from the times when Perl had only dynamic scoping. Lexical scoping is much more natural for the programmer and much safer in many situations. my variables belong to the scope (block, package, or file) in which they are declared.
local variables instead actually belong to a global namespace. If you refer to a variable $x with local, you are actually referring to $main::x, which is a global variable. Contrary to what it's name implies, all local does is push a new value onto a stack of values for $main::x until the end of this block, at which time the old value will be restored. That's a useful feature in and of itself, but it's not a good way to have local variables for a host of reasons (think what happens when you have threads! and think what happens when you call a routine that genuinely wants to use a global that you have localized!). However, it was the only way to have variables that looked like local variables back in the bad old days before Perl 5. We're still stuck with it.
“我的”变量仅在当前代码块中可见。 “局部”变量在以前可见的地方也可见。 例如,如果您说“my $x;” 并调用子函数,它看不到变量 $x。 但如果你说“本地$/;” (将记录分隔符的值清空)然后您可以更改在您调用的任何函数中读取文件的方式。
在实践中,你几乎总是想要“我的”,而不是“本地的”。
"my" variables are visible in the current code block only. "local" variables are also visible where ever they were visible before. For example, if you say "my $x;" and call a sub-function, it cannot see that variable $x. But if you say "local $/;" (to null out the value of the record separator) then you change the way reading from files works in any functions you call.
In practice, you almost always want "my", not "local".
dinomite 使用 local 重新定义记录分隔符的示例是我在大量 perl 编程中遇到的唯一一次。 我生活在一个利基 perl 环境 [安全编程] 中,但根据我的经验,它确实是一个很少使用的范围。
dinomite's example of using local to redefine the record delimiter is the only time I have ran across in a lot of perl programming. I live in a niche perl environment [security programming], but it really is a rarely used scope in my experience.
我认为最容易记住的方法就是这样。 MY 创建一个新变量。 LOCAL 临时更改现有变量的值。
I think the easiest way to remember it is this way. MY creates a new variable. LOCAL temporarily changes the value of an existing variable.
正如 testlocal 评论中提到的,声明“local $x;” 意味着 $x 现在是 undef
As mentioned in testlocal comment, declaring "local $x;" means that $x is now undef
简而言之,
my
在词法作用域中将变量标记为私有,而local
在动态作用域中将变量标记为私有。更容易理解
my
,因为它创建了通常意义上的局部变量。 创建了一个新变量,并且只能在封闭的词法块内访问它,该词法块通常用花括号标记。 大括号规则有一些例外,例如:但这只是 Perl 做你的意思。 通常情况下,您会遇到这样的情况:
在这种情况下,
$x
是子例程私有的,并且其范围由大括号括起来。 需要注意的是,与local
不同的是,my
变量的范围是根据文件中写入的代码定义的。 这是一个编译时现象。要理解
本地
,您需要考虑程序运行时的调用堆栈。 当变量是local
时,它会从对堆栈上低于该变量的所有内容执行local
语句的位置开始重新定义,直到将堆栈返回给调用者包含local
的块的。一开始这可能会令人困惑,所以请考虑以下示例。
当
foo
第一次被调用时,它看到$x
的全局值是1。当bar
被调用并且local时$x
运行,重新定义堆栈上的全局$x
。 现在,当从bar
调用foo
时,它会看到$x
的新值 2。 到目前为止,这并不是很特别,因为如果不调用local
也会发生同样的事情。 神奇的是,当bar
返回时,我们退出由local $x
创建的动态作用域,并且之前的全局$x
返回到作用域。 因此,对于foo
的最终调用,$x
为 1。您几乎总是想使用
my
,因为这为您提供了局部变量您正在寻找。 千载难逢,local
确实可以方便地做一些很酷的事情。The short answer is that
my
marks a variable as private in a lexical scope, andlocal
marks a variable as private in a dynamic scope.It's easier to understand
my
, since that creates a local variable in the usual sense. There is a new variable created and it's accessible only within the enclosing lexical block, which is usually marked by curly braces. There are some exceptions to the curly-brace rule, such as:But that's just Perl doing what you mean. Normally you have something like this:
In that case,
$x
is private to the subroutine and its scope is enclosed by the curly braces. The thing to note, and this is the contrast tolocal
, is that the scope of amy
variable is defined with respect to your code as it is written in the file. It's a compile-time phenomenon.To understand
local
, you need to think in terms of the calling stack of your program as it is running. When a variable islocal
, it is redefined from the point at which thelocal
statement executes for everything below that on the stack, until you return back up the stack to the caller of the block containing thelocal
.This can be confusing at first, so consider the following example.
When
foo
is called the first time, it sees the global value of$x
which is 1. Whenbar
is called andlocal $x
runs, that redefines the global$x
on the stack. Now whenfoo
is called frombar
, it sees the new value of 2 for$x
. So far that isn't very special, because the same thing would have happened without the call tolocal
. The magic is that whenbar
returns we exit the dynamic scope created bylocal $x
and the previous global$x
comes back into scope. So for the final call offoo
,$x
is 1.You will almost always want to use
my
, since that gives you the local variable you're looking for. Once in a blue moon,local
is really handy to do cool things.动态范围界定。 这是一个简洁的概念。 很多人不使用它,也不理解它。
基本上可以将
my
视为创建一个变量并将其锚定到一个 {} 块(又称作用域)。所以
my
变量就是您所习惯的。 而使用动态作用域 $var 可以在任何地方声明并在任何地方使用。因此,使用
local
,您基本上暂停了该全局变量的使用,并使用“本地值”来处理它。 因此local
为临时变量创建一个临时作用域。这应该打印:
Dynamic Scoping. It is a neat concept. Many people don't use it, or understand it.
Basically think of
my
as creating and anchoring a variable to one block of {}, A.K.A. scope.So a
my
variable is what you are used to. whereas with dynamic scoping $var can be declared anywhere and used anywhere.So with
local
you basically suspend the use of that global variable, and use a "local value" to work with it. Solocal
creates a temporary scope for a temporary variable.This should print:
引用自学习Perl:
因此,
local
保存全局变量的当前值,然后将其设置为某种形式的空值。 您经常会看到它用于读取整个文件,而不是仅引导一行:调用
local $/
将输入记录分隔符(Perl 停止读取“行”的值)设置为空值,导致 spaceship 运算符读取整个文件,因此它永远不会命中输入记录分隔符。Quoting from Learning Perl:
So,
local
saves a global variable's current value and then set it to some form of empty value. You'll often see it used to slurp an entire file, rather than leading just a line:Calling
local $/
sets the input record separator (the value that Perl stops reading a "line" at) to an empty value, causing the spaceship operator to read the entire file, so it never hits the input record separator.我不敢相信没有人链接到 Mark Jason Dominus 关于这一问题的详尽论文:
应对范围
之后,如果您想知道
local
到底有什么用处,local
的七个有用用途I can’t believe no one has linked to Mark Jason Dominus’ exhaustive treatises on the matter:
Coping with Scoping
And afterwards, if you want to know what
local
is good for after all,Seven Useful Uses of
local
http://perldoc.perl.org/perlsub.html#私有变量-via-my()
http://perldoc.perl.org/perlsub.html#临时值via-local()
我认为这根本不清楚,除了说“本地到封闭块”之外,它的意思是当块退出时恢复原始值。
http://perldoc.perl.org/perlsub.html#Private-Variables-via-my()
http://perldoc.perl.org/perlsub.html#Temporary-Values-via-local()
I don't think this is at all unclear, other than to say that by "local to the enclosing block", what it means is that the original value is restored when the block is exited.
谷歌在这方面确实很适合你:http://www.perlmonks.org/?node_id=94007
来自链接:
通常使用 my,它更快并且不会做任何奇怪的事情。
Well Google really works for you on this one: http://www.perlmonks.org/?node_id=94007
From the link:
Generally use my, it's faster and doesn't do anything kind of weird.