6.13 作用域规则:全局、字典、动态
标识符的“作用域”是指程序中一个特定的部分。只有在这个部分中,才可以对此标识符进行引用。有的标识符可在程序的任何地方引用;另一些则只能在有限的部分总才能引用。
对一个标识符来说,通常可选择3种作用域: 全局作用域、字典作用域、动态作用域。
全局作用域在程序执行的任何阶段都可以使用,而且可在程序任何的地方对其进行修改。
假如不加任何前缀来定义一个变量,那么它会默认为全局变量,有一个全局作用域。
对于“字典作用域”来说,只有在定义它的那个代码块中才能使用它。而对“动态作用域变量”来说,只有从它的创建位置开始,一直到当前块结束前才可以使用它。注意对块内的子程序来说,只要在允许的范围内,那么一样可以访问这些变量。
下面这个程序展示了全局、字典、动态变量的作用域问题。
-------------------------------------------------------------------------
1 #!/usr/bin/perl
2 # Fig. 6.16: fig06_16.pl
3 # Demontrating variable scope.
4
5 # before global variables are defined, call subroutine1
6 print "Without globals:\n";
7 subroutine1();
8
9 # define global variables
10 our $x = 7;
11 our $y = 17;
12
13 # call subroutine1 to see results with defined global variables
14 print "\nWith globals:";
15 print "\nglobal \$x: $x";
16 print "\nglobal \$y: $y\n";
17 subroutine1();
18 print "\nglobal \$x: $x";
19 print "\nglobal \$y: $y\n";
20 subroutine2();
21 # subroutine1 displays its own $x (lexical scope )
22 # and $y (dynamic scope) variables, then calls subroutine2
23 sub subroutine1
24 {
25 my $x = 10;
26 local $y = 5;
27 print "\$x in subroutine1: $x\t(lexical to subroutine1)\n";
28 print "\$y in subroutine1: $y\t(dynamic to subroutine1)\n";
29 subroutine2();
30 }
31
32 # subroutine2 displays global $x and subroutine1's $y which
33 # has dynamic scope
34 sub subroutine2
35 {
36 print "\$x in subroutine2: $x\t(global)\n";
37 print "\$y in subroutine2: $y\t(dynamic to subroutine1)\n";
38 }
39
--------------------------------------------------------------------
程序的输出如下:
Without globals:
$x in subroutine1: 10 (lexical to subroutine1)
$y in subroutine1: 5 (dynamic to subroutine1)
$x in subroutine2: (global)
$y in subroutine2: 5 (dynamic to subroutine1)
With globals:
global $x: 7
global $y: 17
$x in subroutine1: 10 (lexical to subroutine1)
$y in subroutine1: 5 (dynamic to subroutine1)
$x in subroutine2: 7 (global)
$y in subroutine2: 5 (dynamic to subroutine1)
global $x: 7
global $y: 17
$x in subroutine2: 7 (global)
$y in subroutine2: 17 (dynamic to subroutine1)
--------------------------------------------------------------------
在这里,our、my、local定义的便是一个变量的作用域。其中,our关键字将一个变量明确定义为全局变量。my关键字定义了一个字典作用域变量。 而local关键字定义了一个动态作用域变量。请记住,在定义中既没有my、也没有local的变量均默认为全局变量。
在定义任何全局变量之前,我们先在第7行调用了soubroutine1子程序(定义在第23-30行)。在这个子程序中,我们定义了一个字典变量$x(在第25行使用关键字my),并将其初始化成10,同时定义了一个动态变量$y(在26行使用local定义),并初始化成5。接下来,subroutine1同时显示了两个变量的值。随后,subroutine1会调用subroutine2(定义于第34-38行)。
在subroutine2中,我们用第36行显示了$x的值。在这个时候,唯一定义好的$x变量是把字典作用域定在subroutine1之内的那个$x---subroutine2是无法“看到”subroutine1的字典作用域变量的。 因此subroutine2会试着寻找一个全局定义的$x。由于暂时无法找到这样的一个定义,所以不会输出一个值。
在第37行,我们让subroutine2显示了变量$y。该变量在subroutine1中被定义在一个动态作用域内。 subroutine1调用subroutine2时,由于subroutine2可访问subroutine1中所有被定义为动态作用域的变量。因此subroutine2可顺利输出subroutine1中的$y变量的值(等于5)。
subroutine1执行完毕后,程序会跳至第10行继续执行。在这个地方,程序用our关键字定义了全局量$x和$y。其中,$x被设置为7,而$y被设为17。请记住,在定义中既没有my、也没有local的变量均默认为全局变量。
良好的编程习惯: 应该用our,my,local明确定义所有变量。
提示:our关键字只能用于Perl的5.6及更高版本。
Perl版主“兰花仙子”的一篇关于变量的作用域的精华文章:
阅读(1896) | 评论(0) | 转发(0) |