我对perl中的local/our
范围几乎没有疑问。我阅读了很多文档,但仍然存在混淆。以下是混淆
什么是local
范围?
我读到的是 - >本地复制全局变量的值,更改值,用户将使用它和块外它将保留全局值
混乱 - > my
做同样的事情。我看到的唯一好处是像$package::var
这样的变量不能用我的范围声明,但可以用本地范围声明。本地还有什么
什么是"全球"变量
所读内容是 - >它的范围在包装内。基本上我们将全局变量放在@EXPORT
数组中并使用它或附加命名空间以在其他包中使用。
my
范围声明变量,那么我们可以在整个包中访问变量。是对的吗?是否可以在my
数组中添加@EXPORT
范围变量并在另一个包中使用它?
我认为全局变量是使用our
关键字声明的。有没有其他方法可以这样做?
这个问题可能看似重复,但我很困惑
答案 0 :(得分:21)
在范围界定方面,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数组中添加my范围变量并在另一个包中使用它?
没有。 Exporter使用@EXPORT
。除了全局符号之外,导出器将无法找到任何内容(因为文件是在新的词法范围中编译的),因此@EXPORT
必须只包含全局符号。
答案 1 :(得分:6)
有两种变量,词法范围和全局范围。
在版本5之前的Perl中,只有全局作用域。这些变量是包变量。如果使用包前缀,这些变量可在程序中的任何位置使用。
引入了local
关键字,以提供一种在有限范围内更改其中一个包全局变量的值的方法,例如在一个子例程中。使用local
语句进入作用域时,它会将旧值保存在堆栈中,退出时,它将恢复旧值。这些仍然是包全局变量,这意味着它们仍然可以在任何地方使用。如果您在具有local
变量的作用域内,并且调用子例程,则该子例程内的该变量仍然可见。
版本5中引入了my
关键字,并提供了词法范围的变量。这些变量仅存在于声明它们的范围内。这意味着如果调用子例程,则my
变量不可见。退出范围后,my
变量就会消失。您应该尽可能使用my
变量,因为您不希望变量在您调用的子例程中可见。您不能在@EXPORT
列表中使用这些类型的变量,因为这些变量在其范围之外是不可见的。
最后,our
关键字是两者的组合,因为它为您提供了一个包全局变量,但该变量是词法范围的。这意味着它将在程序的任何位置可用,但在封闭块的末尾,您不能再引用该变量。
答案 2 :(得分:5)
sub mess_with_foo {
$foo=0;
}
sub myfunc {
my $foo=20;
mess_with_foo();
print $foo;
}
myfunc();
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 $foo
的范围之外,local $foo
和myfunc()
都不会被看到。
答案 3 :(得分:0)
这是我发现的有关变量作用域的内容: 如果在块内使用,我的贴图非常清楚直接。如果在任何块外部的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 }