在Perl中,local()可以创建一个变量吗?

suh*_*hel 7 perl scope

我在Stackoverflow和Google中读过很多帖子,告诉我们local不会创建变量,而是在现有的变量上工作.

我在下面有一小段代码,我想知道local在没有创建这样的变量时如何工作.

#use strict;
#use warnings;

&func;

sub func{
    local $temp = 20;
    print $temp;        
}
Run Code Online (Sandbox Code Playgroud)

我写这篇文章只是为了理解这个概念而且我对Perl来说相对较新.

bri*_*foy 8

除非使用声明变量,否则my没有完整包规范的变量将进入当前包.以下是您第一次看到变量的用法以及它们的用途:

my $temp;       # a scoped, lexical variable that does not live in any package
state $temp;    # a persistent lexical variable
our $temp;      # a package variable in the current package, declared
$temp;          # a package variable in the current package
$main::temp     # a package variable in main
$Foo::Bar::temp # a package variable in Foo::Bar
local $temp     # a package variable in the current package, with a dynamically-scoped (temporary) value
Run Code Online (Sandbox Code Playgroud)

local套包变量的范围.当您声明这个"动态"范围时,Perl会使用您设置的临时值,直到范围结束.与其他包变量一样,Perl在您第一次使用它们时会创建它们.您可以先local在前面使用它并不会影响它.

许多试图回答你问题的人立即唠叨你strict.这是一个编程辅助工具,它可以帮助您通过强制声明要使用的所有变量来错误输入变量名.当您使用未声明的变量名时,它会停止编译程序.你可以做到这一点与vars编译,my,state,或our:

use vars qw($temp);
our $temp;
my $temp;
state $temp;
Run Code Online (Sandbox Code Playgroud)

local正如你所见,不是其中的一部分.为什么?因为那就是它的样子.如果不同的话,我会更喜欢它.

strict如果您使用完整的包规范,将不会抱怨,例如$Foo::Bar::temp.你可以错误地输入所有这些但没有注意到.

我主要保留我local对Perl特殊变量的使用,你不必申报.如果我想$_在子例程中使用,也许使用$_默认使用的运算符,我可能会从以下开始local $_:

 sub something {
     local $_ = shift @_;
     s/.../.../;
     tr/.../.../;
     ...;
     }
Run Code Online (Sandbox Code Playgroud)

我可能local更频繁地使用输入记录分隔符,所以我可以使用不同的行结尾而不影响之前的可能性:

 my $data = do { local $/; <FILE> };
Run Code Online (Sandbox Code Playgroud)

那些工作是因为隐含的第一次使用那些你没见过的变量.

否则,我可能希望将变量设置为其子例程的私有,因此子例程之外的任何内容都无法看到它.在这种情况下,我不希望程序的其余部分可以读取或写入的包变量.这是my变量的工作:

sub something {
    my $temp = ...;

    }
Run Code Online (Sandbox Code Playgroud)

编程的诀窍是限制你想要的东西.如果您的程序的其余部分无法查看或更改变量,那么my就是要走的路.

我解释这是学习Perl并写下Mastering Perl中包变量的细节.

  • 如果冗长而琐碎的答案在没有评论的情况下得到落实,那么我很生气. (2认同)

Сух*_*й27 5

local不会创建变量,而是在现有变量上工作.但我在下面有一小段代码,我想知道当没有这样的变量已经创建时本地是如何工作的.

让我们做几步,让perl做一些诊断,

perl -wE 'local $temp =3'
Name "main::temp" used only once: possible typo at -e line 1.
Run Code Online (Sandbox Code Playgroud)

所以local $temp改变$main::temp哪个是包变量和

perl -wE 'local $main::temp =3'
Name "main::temp" used only once: possible typo at -e line 1.
Run Code Online (Sandbox Code Playgroud)

发出同样的警告.所以我们创建了一个本地化的新包变量.

这是什么意思?这意味着不像our $temp它保持package('global')变量$ temp的值,直到它退出封闭块,此时它将值恢复为先前的值.

还有一些测试,

perl -MData::Dumper -E 'say Dumper [exists $main::{t}, ${$main::{t}}]'
$VAR1 = [
      '',     # `$main::t` is NOT created in main package
      undef   # retrieving value of `$main::t` thus returns undef
    ];
Run Code Online (Sandbox Code Playgroud)
perl -MData::Dumper -E '{our $t=7} say Dumper [exists $main::{t}, ${$main::{t}}]'
$VAR1 = [
      1,      # `$main::t` is created in main package
      7       # value of `$main::t`
    ];
Run Code Online (Sandbox Code Playgroud)

最后,

perl -MData::Dumper -E '{local $t=7} say Dumper [exists $main::{t}, ${$main::{t}}]'
$VAR1 = [
      1,      # `$main::t` is *CREATED* in main package
      undef   # value of `$main::t` reverts to undef at exit of enclosing block
    ];
Run Code Online (Sandbox Code Playgroud)


Håk*_*and 0

你忘了使用use strict. 如果不这样做,将使用use strict全局包变量。请参阅http://perlmaven.com/global-symbol-requires-explicit-package-name$temp

包变量始终是全局的。它们有一个名称和一个包限定符。您可以省略包限定符,在这种情况下,Perl 使用默认值,您可以使用包声明来设置它。为了避免意外使用全局变量,请添加use strict 'vars'到您的程序中。从文档中:

use strict vars:如果您访问既未显式声明(使用 my、our、state 或 use vars 中的任何一个)也未完全限定的变量,则会生成编译时错误。(因为这是为了避免变量自杀问题和微妙的动态范围问题,所以仅仅局部变量是不够的。)

  • 这并没有回答问题,并且包含无助于解决此问题的烦人的唠叨。 (2认同)