perl中的局部变量和全局变量

Nit*_*esh 16 perl scope

我对local/ourperl的范围几乎没有疑问.我阅读了很多文档,但仍然存在混淆.以下是混乱

  1. 什么是local范围?

    我读的是 - >本地复制全局变量的值,更改值,用户将使用它和块外它将保留全局值

    混乱 - > my做同样的事情.我看到的唯一好处是,某些变量$package::var不能用我的作用域声明,但可以用本地作用域声明.还有什么适合当地的

  2. 什么是"全球"变量?

读的是 - >它的范围在包内.基本上我们将全局变量放在@EXPORT数组中并使用它或附加命名空间以在其他包中使用.

怀疑 - >再次,如果我们my在main中声明带范围的变量,那么我们可以在整个包中访问变量.是对的吗?是否可以my@EXPORT数组中添加范围变量并在另一个包中使用它?

我认为全局变量是用our关键字声明的.有没有其他方法可以这样做?

这个问题可能看似重复,但我很困惑

ike*_*ami 22

在范围界定方面,Perl中有两种变量.

  • 词汇变量是词法范围的,这意味着它们仅在当前词法范围内可见.
  • 包变量是全局范围的,这意味着解释器中的所有代码都可以看到它们.

以下是创建变量的方法.

  • my 创建一个词法变量.
  • our创建一个词法变量,该变量别名为当前包中同名变量.换句话说,our $foo;就是一样alias my $foo = $The::Current::Package::foo;.
  • 全局变量是在使用时创建的.

local不会创建任何变量.它只是备份一个变量,直到当前的词法范围被销毁.


my 做同样的事情.

local不会改变变量的作用域.虽然词法变量仅在词法范围内可见,但是整个解释器仍然可以看到本地化的全局变量.

$x = 123;
sub foo { print "$x\n"; }
{ local $x = 456; foo(); }  # 456
foo();                      # 123
Run Code Online (Sandbox Code Playgroud)

$x = 123;
sub foo { print "$x\n"; }
{ my $x = 456; foo(); }   # 123
foo();                    # 123
Run Code Online (Sandbox Code Playgroud)

还有什么 local

local主要用于近似my不能以词法方式声明的变量的功能.

(从历史上看,这就是所有变量.从5.6开始,只能在词法上声明标点符号变量.)


什么是"全球"变量?

可以全局看到的变量,即解释器中的任何代码.


是否可以在@EXPORT数组中添加my范围变量并在另一个包中使用它?

编号@EXPORT由出口商使用.除了全局符号之外,导出器将无法找到任何内容(因为文件是在新的词法范围中编译的),因此@EXPORT只能包含全局符号.


Kev*_*nko 6

有两种变量,词法范围和全局范围.

在版本5之前的Perl中,只有全局作用域.这些变量是包变量.如果使用包前缀,这些变量可在程序中的任何位置使用.

所述local关键字被引入到提供了一种方式,以改变一个有限范围内这些包全局变量,诸如一个子例程中的一个的值.当使用local语句输入范围时,它将在堆栈上保存旧值,并在退出时,它将恢复旧值.这些仍然是包全局变量,这意味着它们仍然可以在任何地方使用.如果您在具有local变量的范围内,并且调用子例程,则该子例程内的该变量仍然可见.

my关键字是在版本5中引入的,并提供了词法范围的变量.这些变量仅存在于声明它们的范围内.这意味着如果调用子例程,则该my变量不可见.退出范围后,my变量就会消失.您应该my尽可能使用变量,因为您不希望变量在您调用的子例程中可见.您不能在@EXPORT列表中使用这些类型的变量,因为这些变量在其范围之外是不可见的.

最后,our关键字是两者的组合,因为它为您提供了一个包全局变量,但该变量是词法范围的.这意味着它将在程序中的任何位置可用,但在封闭块的末尾,您不能再引用该变量.

  • `local`变量的范围取决于运行时发生的情况.变量的作用域从"local"开始,并在封闭块的末尾结束,但该变量的作用域还包括在它们之间调用的所有子程序.相比之下,`my`变量具有静态范围,因为它不会根据运行时发生的变化而变化. (2认同)

小智 6

例1:

sub mess_with_foo {
      $foo=0;
 }

 sub myfunc {
      my $foo=20;
      mess_with_foo();
      print $foo;
 }
 myfunc();
Run Code Online (Sandbox Code Playgroud)

例2:

 sub mess_with_foo {
      $foo=0;
 }

 sub myfunc {
      local $foo=20;
      mess_with_foo();
      print $foo;
 }
 myfunc();
Run Code Online (Sandbox Code Playgroud)

示例1打印20因为mess_with_foo()看不到my $foo.它无法改变它. my $foo只能在其范围内看到myfunc().

示例2 打印,0因为mess_with_foo()可以查看my $foo和更改它.local $foo可以在其范围内看到myfunc()AND在其范围内调用的任何函数的范围myfunc().

这是唯一的区别.既my $foo不会也local $foo不会在他们的范围之外被看到myfunc().


小智 6

这是我发现的关于变量作用域的内容:

my如果在块内使用,声明将非常清晰和直接。如果在任何块外的 main 中使用,它们有点不同,这意味着my在块外声明的变量即使在从同一文件内的任何地方调用的函数内也是可见的,只要这些函数是在同一文件中定义的。但是,如果在块内声明,即使从同一块调用它们,它们对函数也不可见。所有my变量似乎都存在于堆栈中。并且:您不能使用local.

our变量存在于堆中。即使你有一个my同名的变量,我们的变量仍然可以通过 访问${'var'},它在符号表中查找该名称的变量并取消引用它。my另一方面,变量没有符号表条目。

local在我看来,变量就像是以前 Perl 版本的遗物。它们只是重新分配给our具有块作用域的全局 ( ) 变量,并在块终止后恢复它们以前的值。我看不出使用它们的真正意义。

我下面的小程序显示了所有这些,它显示了除了众所周知的 defined() 测试之外,缺少声明的() 测试是如何识别未声明的变量。

 #!/usr/bin/perl

 use strict;

 ### This is about variable scoping with my, our and local
 my $fsv = "file scope";                 # visible for all code in this file
 our $gsv = "global scope";              # not different from my $fsv, except in packages
 our $lsv = "global";                    # global scope, but localized in subsequent block

 {
    my $bsv = "lex scope";               # visible only inside this block, not even in subs called from here
    $gsv = "visible everywhere";
    local $lsv = "global, but localized val";

    print "This is variable \$bsv with value $bsv inside block\n";
    print "This is variable \$fsv with value $fsv inside block\n";
    print "This is variable \$lsv with value $lsv inside block\n\n";
    print_vars("calledfromblock");
 }

 print_vars("calledfromoutside");


 no strict 'vars';                       # needed if testing variable for declaredness rather than definedness
 if ( defined $bsv ) {
    print "\$bsv as defined outside braces: $bsv\n"
 } else {
    print "\$bsv not defined outside braces\n";
 }
 print "This is variable \$lsv with value $lsv outside block\n";
 # use strict 'vars';                    # no strict 'vars' effective even in sub print_vars unless switched back on

 sub print_vars
 {
    my $whence = shift;
    my $gsv = "my variable";
    no strict 'refs';                    # needed to access the global var $gsv using ${'gsv'} despite the my declaration

    if ( $whence eq "calledfromblock" ) {
       print "\t print_vars called from within the block:\n";
       ( defined $bsv )     ? print "\$bsv is $bsv inside sub\n"     : print "\$bsv not defined inside sub\n";
       ( defined $fsv )     ? print "\$fsv is $fsv inside sub\n"     : print "\$fsv not defined inside sub\n";
       ( defined ${'gsv'} ) ? print "\$gsv is ${'gsv'} inside sub\n" : print "\$gsv not defined inside sub\n";
       ( defined ${'lsv'} ) ? print "\$lsv is ${'lsv'} inside sub\n" : print "\$lsv not defined inside sub\n";
    } else {
       print "\t print_vars called from outside the block:\n";
       ( defined $bsv ) ? print "\$bsv is $bsv inside sub\n" : print "\$bsv not defined inside sub\n";
       ( defined $fsv ) ? print "\$fsv is $fsv inside sub\n" : print "\$fsv not defined inside sub\n";
       ( defined $gsv ) ? print "\$gsv is $gsv inside sub\n" : print "\$gsv not defined inside sub\n";
       ( defined $lsv ) ? print "\$lsv is $lsv inside sub\n" : print "\$lsv not defined inside sub\n";
    }
    print "\n";
 }
Run Code Online (Sandbox Code Playgroud)