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

问题描述 投票:15回答:4

我对Perl中的local/our范围毫不怀疑。我读了很多文档,但是我仍然感到困惑。以下是混淆]

  1. local范围是什么?

    我读到的是->局部复制全局变量的值,更改该值,用户将使用它,并且在块外它将保留全局值

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

  2. 什么是“全局”变量?

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

doubt->同样,如果我们仅在main中以my范围声明变量,则可以在整个包中访问该变量。那正确吗?是否可以在my数组中添加@EXPORT作用域变量,并在其他程序包中使用它?

我认为全局变量是用our关键字声明的。还有其他方法吗?

这个问题可能看起来很重复,但是我很困惑。

perl scope
4个回答
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

$x = 123;
sub foo { print "$x\n"; }
{ my $x = 456; foo(); }   # 123
foo();                    # 123

local还有什么?>

[local主要用于为无法以词法声明的变量近似my的功能。

(从历史上讲,这就是所有变量。从5.6开始,不能按词法声明标点符号。)


什么是“全局”变量?

一个可以全局查看的变量,即可以通过解释器中的任何代码查看的变量。]​​>


是否可以在@EXPORT数组中添加我的作用域变量,并在其他包中使用它?

没有@EXPORT由导出程序使用。导出程序将无法找到全局符号,因为文件是在新的词法范围内编译的,因此@EXPORT必须仅包含全局符号。

有两种变量,按词法作用域和全局作用域。

在版本5之前的Perl中,只有全局范围的。这些变量是包变量。如果使用包前缀,则这些变量在程序中随处可见。

local关键字的引入是为了提供一种在有限范围内(例如在一个子例程中)更改这些程序包全局变量之一的值的方法。使用local语句进入作用域时,它将旧值保存在堆栈中,退出时将恢复旧值。这些仍然是程序包全局变量,这意味着它们仍然可以在任何地方使用。如果您在具有local变量的作用域内,并且调用了子例程,则该变量在该子例程内仍然可见。

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

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

示例1:

sub mess_with_foo {
      $foo=0;
 }

 sub myfunc {
      my $foo=20;
      mess_with_foo();
      print $foo;
 }
 myfunc();

示例2:

 sub mess_with_foo {
      $foo=0;
 }

 sub myfunc {
      local $foo=20;
      mess_with_foo();
      print $foo;
 }
 myfunc();

示例1打印20,因为mess_with_foo()看不到my $foo。它无法更改。 my $foo仅在其myfunc()范围内可见。

示例2打印0,因为mess_with_foo()可以看到my $foo并进行更改。在local $foo的范围内以及在myfunc()的范围内调用的任何函数的范围内都可以看到myfunc()

这是唯一的区别。 my $foolocal $foo都不会超出myfunc()的范围。

这是我发现的有关可变范围的内容:如果在块内使用,我的贴图非常清楚直接。如果在任何块外部的main中使用它们,则它们有所不同,这意味着即使在同一文件内的任何位置调用的函数内部,只要在同一文件中定义了这些变量,就可以看到在块外部声明的my变量。但是,如果在块内声明,则即使从同一块中调用它们也对函数不可见。我所有的变量似乎都存在于堆栈中。并且:您无法使用local将其本地化。

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

本地变量在我看来就像是以前的perl版本中的遗物。它们只是重新分配给具有块范围的全局(我们的)变量,并在块终止后恢复其先前的值。使用它们没有真正意义。

我下面的小程序显示了所有这些内容,它显示了在众所周知的define()测试之外,缺少声明的()测试来标识未声明的变量的严重程度。

  1 #!/usr/bin/perl
  2
  3 use strict;
  4
  5 ### This is about variable scoping with my, our and local
  6 my $fsv = "file scope";                 # visible for all code in this file
  7 our $gsv = "global scope";              # not different from my $fsv, except in packages
  8 our $lsv = "global";                    # global scope, but localized in subsequent block
  9
 10 {
 11    my $bsv = "lex scope";               # visible only inside this block, not even in subs called from here
 12    $gsv = "visible everywhere";
 13    local $lsv = "global, but localized val";
 14
 15    print "This is variable \$bsv with value $bsv inside block\n";
 16    print "This is variable \$fsv with value $fsv inside block\n";
 17    print "This is variable \$lsv with value $lsv inside block\n\n";
 18    print_vars("calledfromblock");
 19 }
 20
 21 print_vars("calledfromoutside");
 22
 23
 24 no strict 'vars';                       # needed if testing variable for declaredness rather than definedness
 25 if ( defined $bsv ) {
 26    print "\$bsv as defined outside braces: $bsv\n"
 27 } else {
 28    print "\$bsv not defined outside braces\n";
 29 }
 30 print "This is variable \$lsv with value $lsv outside block\n";
 31 # use strict 'vars';                    # no strict 'vars' effective even in sub print_vars unless switched back on
 32
 33 sub print_vars
 34 {
 35    my $whence = shift;
 36    my $gsv = "my variable";
 37    no strict 'refs';                    # needed to access the global var $gsv using ${'gsv'} despite the my decaration
 38
 39    if ( $whence eq "calledfromblock" ) {
 40       print "\t print_vars called from within the block:\n";
 41       ( defined $bsv )     ? print "\$bsv is $bsv inside sub\n"     : print "\$bsv not defined inside sub\n";
 42       ( defined $fsv )     ? print "\$fsv is $fsv inside sub\n"     : print "\$fsv not defined inside sub\n";
 43       ( defined ${'gsv'} ) ? print "\$gsv is ${'gsv'} inside sub\n" : print "\$gsv not defined inside sub\n";
 44       ( defined ${'lsv'} ) ? print "\$lsv is ${'lsv'} inside sub\n" : print "\$lsv not defined inside sub\n";
 45    } else {
 46       print "\t print_vars called from outside the block:\n";
 47       ( defined $bsv ) ? print "\$bsv is $bsv inside sub\n" : print "\$bsv not defined inside sub\n";
 48       ( defined $fsv ) ? print "\$fsv is $fsv inside sub\n" : print "\$fsv not defined inside sub\n";
 49       ( defined $gsv ) ? print "\$gsv is $gsv inside sub\n" : print "\$gsv not defined inside sub\n";
 50       ( defined $lsv ) ? print "\$lsv is $lsv inside sub\n" : print "\$lsv not defined inside sub\n";
 51    }
 52    print "\n";
 53 }

6
投票

有两种变量,按词法作用域和全局作用域。


6
投票

示例1:


0
投票

这是我发现的有关可变范围的内容:如果在块内使用,我的贴图非常清楚直接。如果在任何块外部的main中使用它们,则它们有所不同,这意味着即使在同一文件内的任何位置调用的函数内部,只要在同一文件中定义了这些变量,就可以看到在块外部声明的my变量。但是,如果在块内声明,则即使从同一块中调用它们也对函数不可见。我所有的变量似乎都存在于堆栈中。并且:您无法使用local将其本地化。

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

© www.soinside.com 2019 - 2024. All rights reserved.