perl local my our 的前世今生

上一篇 / 下一篇  2008-12-07 12:17:31 / 个人分类:perl

  • 文件版本: V1.0
  • 开发商: 本站原创
  • 文件来源: 本地
  • 界面语言: 简体中文
  • 授权方式: 免费
  • 运行平台: Win9X/Win2000/WinXP
51Testing软件测试网,Zr x V^ se

Perl中的变量作用范围 local, my, our与全局变量51Testing软件测试网"V nH}$SL$S_&_
51Testing软件测试网 j\ x2E~ H!gX
很古老很古老以前......嗯,不用老到白垩纪,那时候的Perl是自由射击的。没有什么定义变量的说法,所有的变量都是全局变量,也不需要任何 定义就可以使用。后来就出现了local, 再后来出现了use strict 'vars'和my, 再后来又有了our......所以今天的Perl大陆就有了崇山巨岭,一些变量就被限制在盆地里,老死于桃花源中也。51Testing软件测试网U!i^%PXZ)bRv
51Testing软件测试网U D]vi i.fU
因为要使用一个跨模块全局变量,研究了一下Perl的变量作用范围,写一点笔记吧。51Testing软件测试网zj&z ~]8e-j

QP8x%s)Q"k7c01. 首先说our, 这个最晚出现但其实质却最早出现的变量修饰符。众所周知,在Perl不使用use strict 'vars'的时候,你可以任意使用变量而不需要实现定义:
1Y(i O)U+FrR0
,?? n Gn#G}0$szStateMachineStatus = undef;51Testing软件测试网#@7k.QJR*rU
51Testing软件测试网{t\j2Oj
这行代码在使用了use strict 'vars'以后是编译不能通过的。如果这个变量是一个全局变量,那么可以定义51Testing软件测试网lOO9N2M
51Testing软件测试网[R3mnF4Q?~
our $szStateMachineStatus = undef;
(H"U#AJY](~051Testing软件测试网9y9h Q ]'C La'_$Z E
这个效果和在不使用use strict 'vars'时一样。"一样"意味着什么呢?51Testing软件测试网Qk;A,quA"i ~7aI

5gQ m|,HW4P0our $szStateMachineStatus = 'init';51Testing软件测试网9xCH td ~
{
$sqUF X}YO]Lj0$szStateMachineStatus = 'inited';
ai!rF5r*TM%y8^0print $szStateMachineStatus;51Testing软件测试网c/dV*F ~7| f!z/g8A$[l
}
+DU#C sy2e}*\"X0print $szStateMachineStatus;
|0BE&N GSLoC0
cM!`}M0vQL2g0打印的结果是两个'inited'。顺便说,用our定义过的变量,可以在任何地方被再次用our定义,仍然和第一个our定义的变量是同一个。51Testing软件测试网G#E F!I ?v#Z E
51Testing软件测试网{9_*g7st a)w%]
2. my
L(Nv"p+O;g6EsQ051Testing软件测试网~7J6]-anRS B
慢慢地有人觉得Perl的"自由射击式"变量定义法则不行,最突出的就是一些常会打错字(typo)的人。假如你定义了一个变量叫$ szStateMachineStatus,可是在某个地方写成了$szStatMachineStatus,少了一个e。因为不use strict啊,所以没有任何警告,可以这样用。结果就是出了错你就慢慢debug去吧,很浪费时间,不符合Perl的懒惰文化。51Testing软件测试网5_8L-w }'}"\ d.l
51Testing软件测试网 YSv"dgCt
然后就有了use strict 'vars'和my。有了use strict 'vars'以后,所有的变量在使用前必须先被定义。my的法则很简单,只在当前作用域起作用。比如说定义了
s9`2N-P/_9@w k0my $szStateMachineStatus;51Testing软件测试网-[tG'N`g-~4T
那么如果是在文件头定义的,作用范围就到文件尾,在子函数里也能用。如果是在子函数里定义的,那么作用范围就只到函数结束。试看以下代码51Testing软件测试网_,lge6T&?;e5N
foreach my $szName (@arrName){
G;fJ_IO0print $szName;
&b tNcVk5w b"~0}
X9r0]$b:jE8GE;p Zu0在这个循环里Perl每次都创建一个新的$szName变量。换句话说,"my"是属于"见到my就新建"的变量。
?2X?.w;RF6I-g0
k1{Cdg'T1jc03. local
$[8ij%m[%xX:]0
;]^O{RhAu0其实这个定义都可以取消了。它是在my还没出现之前的一个权宜方案。比如说一个变量$i被定义成了全局变量,可是你又想暂时使用一个也叫$i的临时变量。
:PO"J*sE/a4~l#}0no strict 'vars';51Testing软件测试网-J,i5LbuS-vSKG$[
$i = 9999;51Testing软件测试网I rV}@)m)g-j&R
{51Testing软件测试网h,Q4Ssy&l
local $i = 7777;51Testing软件测试网 }_zD;Ia)P
print "$i\n";51Testing软件测试网5{u0b4G6kMk
}51Testing软件测试网t.A2r3N n;z
print "$i\n";51Testing软件测试网w"Zk3A]LN
结果是7777, 9999。在出了local的作用域以后$i又回到了原来的值。在出现了my以后,没有任何理由需要使用local了,请忘记掉它吧。51Testing软件测试网]8a6]o O2e,u
51Testing软件测试网{ \:}m9rnC:\
4. 最后一个话题,全局变量
B$j,{ `ZXH3C$U0
S4oi U\4E0当你只有一个pl文件时,很简单,把你的全局变量在文件头部定义成our就行。可能你会看到有些书上说要使用use vars qw( $szVersion $szToolName); 这样的方式来把 $szVersion和$szToolName定义成全局变量。注意了,use vars的用法是在my出现后,our出现之前的一个历史的盲肠。our的语法更自然,更易于理解,为什么不用our呢? --另外,在文件头把变量定义成my, 也是全局可用的,但是冒了风险,假如在某个函数里用my再定义一次,原来的值可就消失了。用our就不存在多次定义会导致丢值的状况。51Testing软件测试网T%I:jY3C6gj-K
51Testing软件测试网)r,uoB]
当你在写一个有一个pl文件,N个pm文件的系统时该如何呢?事实上Perl里的变量和函数名都有一个系统级的名字。比如说你在某pm文件的头上定义了包名和全局变量51Testing软件测试网#CQj C8{&z
package bagua;51Testing软件测试网6]Y5xE3@']+WH
our $east = 'wood';
9Fab;n]'n0u0那么在任何地方,任何pm和pl文件里都可以使用$bagua::east来访问这个变量。$bagua::east就被称为系统级名字。这也能回答一个问题,为什么不同的perl包里面定义的同名全局变量间不会冲突,因为它们都被限制在包的名字空间下面了。
&Q"V9z)k%Z0
}j C1Ta9DNc0如果你是在pl里定义全局变量,而且该文件没有定义package名字怎么办?Perl会生成一个缺省的package,名字叫"main"。所以如果你的pl文件是这样51Testing软件测试网t'j W w|6?,X%Qu}
our $szVersion = '1.0.1";
3Ii3pva0那么在其它文件里就可以用$main::szVersion来访问,并不需要你定义package main.51Testing软件测试网8S{ V(O!}f*}8V
最后,说一个邪门招式。你可以试一下定义任意一个含有::的变量
3_B zrBT0our $gColor::Blue = '0x0000FF';
(k rp'N/k;q;h x*T0这个变量就在任何地方可用,哪怕你从来没有定义过gColor这个package。这个是Perl的灵活性的体现,它看到这个就自动生成了gColor这个名字空间。当然,我不鼓励这种无厘头的用法。

Y:a K'Q3rK0

K d&a?8{~0老实说,这个东西有点折腾人,主要是书上的表述很晦涩,其实搞懂不难。51Testing软件测试网OZ Nvm$M*A&F
 
0Wlci*D0s0our,"把名字限于某个范围“,其实就是明确声明一个"全局变量",虽然是在某个模块或者函数里面定义的,外面的也可以访问,如果已经声明过了,再次用"our",表示此处用的是全局的那个,不是同名的私有或者局部变量
A3g#NR9fT"M([0 
Jy+L*``4K\7`$P0our $PROGRAM_NAME = "waiter";
'rRoxk4A~w0{
-[-S7z L(HX/n0 51Testing软件测试网4{VQ*aP8G_%K
my $PROGRAM_NAME = "something";51Testing软件测试网Dn Ji)k
our $PROGRAM_NAME = "server"; #这里的our和外面的相同,和前句不同。51Testing软件测试网*}~5u$U+C,Y:kj~
# 这里调用的代码看到的是"server"51Testing软件测试网 j:c9vy?1`;c
}
z#p m|Q1^:e\#~|0Mb0# 这里执行的代码看到的仍然是"server".51Testing软件测试网5P,[PUq~a
 51Testing软件测试网}&EIk ~"Q
my ,"把名字和值都限于限于某个范围",简单说,就是只能本层模块或者函数可以看到这个变量,高一层的或者低一层的都看不到的。51Testing软件测试网IbC#\ t%YYX
sub greeting1{
&U^1hR&R:ly6l0  my ($hello) = "How are you do?";51Testing软件测试网 ].FUZ(W[
  greeting2();51Testing软件测试网V {2p['}
 }
p-zwu+xxP*_0 51Testing软件测试网z.@h&KYwG7h?
sub greeting2{51Testing软件测试网;]2H'_`g7y JHe
  print "$hello\n";51Testing软件测试网 R4o,j7h4TJT.?
}51Testing软件测试网o)Wwp n
$hello = "How are you doing?";51Testing软件测试网\ZVf!u
greeting2();51Testing软件测试网:u&m vqv&}
greeting1();51Testing软件测试网6^,du)rkKd
greeting2();51Testing软件测试网a9ilYRUk
 51Testing软件测试网1e9X(HAU
运行结果:
~Q)DTP(o0How are you doing?51Testing软件测试网s%g!S-\W0~+B!z;i
How are you doing?
h,@K o-M}m5f0How are you doing?
%G[^F$^w0--------------------------
,U |VAi,KJ6mj0一个 How are you do? 都没有,在greeting1中call greeting2时,greeting2看不到greeting1的私有 $hello变量,只能看到外面的全局变量$hello51Testing软件测试网%z F"} `v:z5h g6C g"[.O
 51Testing软件测试网8hAL Ikp0@pHj
local,"把值局限于某个范围",也有叫"动态词法范围",有点不好懂。我的理解,就是本层和本层下层的函数可以看到本层的变量,但是本层上一层的不可以。到底范围是多少,不仅取决于本层的函数,还要看下一层的程序长度和深度,所以叫"动态范围"。51Testing软件测试网,N;u+y+X'jYgz
 51Testing软件测试网N2~,K0md7m*hQ$W
sub greeting1{
8[,YB.pH+_0  local ($hello) = "How are you do?";
N.Op*@\.b0  greeting2();
QS w0E$Nc In0 }51Testing软件测试网g([we w5U{-?*r
 
I ?"j.cp ?t5F*A0sub greeting2{51Testing软件测试网(]Ln2ZR
  print "$hello\n";51Testing软件测试网o*U1A U-o5E?
}51Testing软件测试网|6pi/G-|H8X3q6cp
$hello = "How are you doing?";
4TFn9}2?-_U]0greeting2();51Testing软件测试网5Yw3h Hj7]
greeting1();
2~4E,i#gFi0greeting2();
7EFjU*Dk.k%z de|0 
(g r6`)B&UE7a\0运行结果:51Testing软件测试网-P t m&nw!y.V9jv6T
How are you doing?
zt}t ps Ku R0How are you do?51Testing软件测试网}'Z.~9}'Ar
How are you doing?51Testing软件测试网&p9Ju HL ?u(N)K-l
-----------------------
rQB ^0ZX1_s N+G0跟用 my 时不一样了吧? 此时在greeting1调用greeting2时,greeting2可以看到greeting1的局部变量$hello,外部的全局变量当然就隐藏了。

|b,TT@U8ts&D(f0

TAG: perl

 

评分:0

我来说两句

Open Toolbar