Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2441713
  • 博文数量: 328
  • 博客积分: 4302
  • 博客等级: 上校
  • 技术积分: 5486
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-01 11:14
个人简介

悲剧,绝对的悲剧,悲剧中的悲剧。

文章分类

全部博文(328)

文章存档

2017年(6)

2016年(18)

2015年(28)

2014年(73)

2013年(62)

2012年(58)

2011年(55)

2010年(28)

分类: PERL

2014-09-13 21:08:00

our,my和local都是用来声明或者定义变量的关键字,他们之间的关系一度令我感到迷惑,现在就一步步的阐述三者之间的区别。一个简单的总结性描述如下:
  • our: 定义或者声明一个全局变量,在当前的包环境下。
  • my: 定义一个新的、局部范围(块或者文件)有效的变量。
  • local: 重新定义局部范围有效的变量,主要用于屏蔽同名的全局变量。

从上面的大致描述上可以看出,my变量才是真正的局部变量,而local变量更像是局部作用的全局变量。根据官方的perl文档(5.20),相比于local,应该使用my,因为my更加快速而且安全。一些例外的情况包括,全局符号变量,全局文件句柄和范式(format)等的修改和使用,也就是说,当在被调用的函数中也需要访问这些变量时,使用local。从这个角度来看,my和local虽然都是局部的变量,但是my是静态的(受限于源文件中的物理位置),local是动态的。


our 和 my 的区别


在分析our,my和local三者的关系之前,首先要弄清楚our和my之间的区别。
从perl5开始,my被用来声明
  • 非package变量,它们是
  • 私有的
  • 新的
  • 非全局的
  • 独立于包的,不能通过包前缀方式访问,如$package_name::variable

our 变量
  • 包变量
  • 全局变量
  • 非私有
  • 不一定是重新建立的,有时仅提示编译器这个是已经存在的全局变量
  • 能通过包前缀方式访问,如$package_name::variable

这里是一段示例代码。
  1. use strict;

  2. for (1 ..2){
  3.     # Both variables are lexically scoped to the block.
  4.     our ($o); # Belongs to 'main' package.
  5.     my ($m); # Does not belong to a package.

  6.     # The variables differ with respect to newness.
  7.     $o ++;
  8.     $m ++;
  9.     print __PACKAGE__, " >> o=$o m=$m\n"; # $m is always 1.

  10.     # The package has changed, but we still have direct,
  11.     # unqualified access to both variables, because the
  12.     # lexical scope has not changed.
  13.     package Fubb;
  14.     print __PACKAGE__, " >> o=$o m=$m\n";
  15. }

  16. # The our() and my() variables differ with respect to privacy.
  17. # We can still access the variable declared with our(), provided
  18. # that we fully qualify its name, but the variable declared
  19. # with my() is unavailable.
  20. print __PACKAGE__, " >> main::o=$main::o\n"; # 5
  21. print __PACKAGE__, " >> main::m=$main::m\n"; # Undefined.

  22. # Attempts to access the variables directly won


my 和 local 的区别


首先看local的情况
  1. $a = 3.14159;
  2. {
  3.   local $a = 3;
  4.   print "In block, \$a = $a\n";
  5.   print "In block, \$::a = $::a\n";
  6. }
  7. print "Outside block, \$a = $a\n";
  8. print "Outside block, \$::a = $::a\n";

  9. # This outputs
  10. In block, $a = 3
  11. In block, $::a = 3
  12. Outside block, $a = 3.14159
  13. Outside block, $::a = 3.14159
local 临时的改变了变量的值,仅仅在所处的区域内。它改变了全局同名变量的值。
而,my 创建了仅在所处区域内有效的,一个符号表中不存在的变量。它对全局同名变量没有任何影响。
  1. $a = 3.14159;
  2. {
  3.   my $a = 3;
  4.   print "In block, \$a = $a\n";
  5.   print "In block, \$::a = $::a\n";
  6. }
  7. print "Outside block, \$a = $a\n";
  8. print "Outside block, \$::a = $::a\n";

  9. # This outputs
  10. In block, $a = 3
  11. In block, $::a = 3.14159
  12. Outside block, $a = 3.14159
  13. Outside block, $::a = 3.14159


从typeglob(类型团)角度看my和local


其实对于 my 和 local ,主要还是和 typeglob 有关系。对于一个 perl 中的变量,都有一个 符号表 与之对应,比如有
  1. $perl = 'a';
  2. @perl = qw / a b c d /;
  3. %perl = ...;
  4. sub perl {};
  5. open(perl,...);
看起来其为同名,不同类型的各种符号,但在perl中,他们都是存放在一个的符号表中的同一个表项中的,都是在名为 perl 的表项。然后通过一个 typeglob 的数据结构来来把各种值分开,typeglob 也就是 *perl
我们不妨做个实验
  1. $a = 'a';@a = qw / a b c /;
  2. print "a is ",$a,"\t",@a,"\n";
  3. print "b is ",$b,"\t",@b,"\n";
  4. *b=*a;
  5. print "now b is ",$b,"\t",@b,"\n";
当我们执行完了 *b=*a;也就是typeglob赋值操作以后,等于说在这个代码段中又建立了一个 符号表项 ,也就是 b,那么这个符号表项所指向的 typeglob 和 a 一样。这样,等于说就同时建立了一个和a关联的b的变量,包括 $b,@b

对于local操作,其实是在这个代码段前,先把此 typeglob 中的各个项的值保存,然后在进行对这些变量的操作和运算,这样的话在该代码段结束前,这些变量“看起来”好象没什么变化,等到该代码段结束了,local的变量就会取出原来备份的值,在替换了现有的值。

而 my 呢?
my 并没有用到 typeglob 和 符号表,my 是在每个代码段都建立一个特殊的地方来专门存储这些变量,而且my的变量中没有了 typeglob 的概念,也就是说 my 中的 $a , @a 都是按一定的顺序存放到一个内存区中的,不会出现 *b=*a 的情况了。而在代码段结束的时候,只要这些变量的引用记数为0,就释放这些变量。
阅读(7290) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~