Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52560
  • 博文数量: 43
  • 博客积分: 1161
  • 博客等级: 少尉
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-24 11:14
文章分类
文章存档

2011年(40)

2010年(3)

分类: Python/Ruby

2011-05-14 18:21:01

有数据样本文件1.txt 
没有缩进的行表示人的名字,紧跟着的有缩进的行是人的 属性.从文件中读取数据,构造一个哈希. 
键(key)为人的名字,对应的值(value)是一个数组的引用,其 中包含了返个人的所有属性.
  1. ##1.txt
  2. The Skipper
  3.     blue_shirt
  4.     hat 05jacket
  5.     preserver
  6.     sunscreen
  7. Professor
  8.     sunscreen
  9.     water_bottle
  10.     slide_rule
  11. Gilligan
  12.     red_shirt
  13.     hat
  14.     lucky_socks
  15.     water_bottle
  1. #!perl
  2. use strict;
  3. use 5.010;
  4. my %provisions;
  5. my $person;
  6. while(<>) {
  7.   chomp;
  8.   next if(/^#+/);
  9.   if(/^\S/) {
  10.     $person=$_;
  11.     $provisions{$person}=[];
  12.   } elsif(/^\s+/) {
  13.     push @{$provisions{$person}},$_;
  14.   }
  15. }
  16. for my $name (keys %provisions) {
  17.   say "$name:";
  18.   for(@{$provisions{$name}}) {
  19.     say "|$_|";
  20.   }
  21. }
这一段程序是自己写的.程序的第10,13行是在模式正确匹 
配后的数据输入.可以看到,使用了变量while的默认变量 $_.也就是说,程序把匹配相应模式的一整行都放进了哈希中.对于人的属性,有空白作为前导,从输出中也可以看出, 前导的空白也在哈希中.
Professor :
|    sunscreen |
|    water_bottle |
|    slide_rule |
Gilligan :
|    red_shirt |
|    hat |
|    lucky_socks |
|    water_bottle|
The Skipper :
|    blue_shirt |
|    hat 05jacket |
|    preserver |
|    sunscreen |
  1. #!perl
  2. use strict;
  3. use 5.010;
  4. my %provisions;
  5. my $person;
  6. while(<>) {
  7.   chomp;
  8.   next if(/^#+/);
  9.   if(/(^\S.*)/) {
  10.     $person=$1;
  11.     $provisions{$person}=[];
  12.   } elsif(/^\s+(.*)/) {
  13.     push @{$provisions{$person}},$1;
  14.   }
  15. }
  16. for my $name (keys %provisions) {
  17.   say "$name:";
  18.   for(@{$provisions{$name}}) {
  19.     say "|$_|";
  20.   }
  21. }
这段程序是书中的解答.在第9,12行中使 用了模式捕获.给哈希赋值时使用捕获到的模式赋值.从输出结果可以看到,哈希中叧包含了需要的值,没有多余的前导空白.
Professor :
|sunscreen |
|water_bottle |
|slide_rule |
Gilligan :
|red_shirt |
|hat |
|lucky_socks |
|water_bottle|
The Skipper :
|blue_shirt |
|hat 05jacket |
|preserver |
|sunscreen |

这段代码以Perl的眼光来看,还是有点罗嗦的.程序中的第11行是可以屏蔽掉的.
  1. #!perl
  2. use strict;
  3. use 5.010;
  4. my %provisions;
  5. my $person;
  6. while(<>) {
  7.   chomp;
  8.   next if(/^#+/);
  9.   if(/(^\S.*)/) {
  10.     $person=$1;
  11.     $provisions{$person}=[];
  12.   } elsif(/^\s+(.*)/) {
  13.     push @{$provisions{$person}},$1;
  14.   }
  15. }
  16. for my $name (keys %provisions) {
  17.   say "$name:";
  18.   for(@{$provisions{$name}}) {
  19.     say "|$_|";
  20.   }
  21. }

这样写之后,程序中没有了对哈希中匿名数组引用的定义. 
假设此时程序要把Skipper的blue shirt存入哈希,会发生什么事情? 
存储动作发生在第13行,此时等价的语句是: 
  1. push @{$provisions{'The Skipper'}},"blue shirt";
但是,由于屏蔽了第11行,此时$provisions{"The Skipper"}并不存在.而程序却还把它当做一个数组的引用来使用.
为了解决返个问题,Perl会自动的在变量中插入一个空匿名数组的引用,并继续之后的操作.在这个程序中,新建立的(Perl自动的)空数组的引用被解引用,并在数组中插 入了(push) blue shirt返个属性.

这样的处理过程叫做autovivification(自动形象化——直译,理解上类似于自动按需构造正确的对象).对于任何不存在的变量,或者是变量的值为undef,如果对其做解引用以取其地址(专业来说,是出于左值上下文),都会被自动的赋值成一个不其右值类型相同的空引用,并继续后继操作. 
This process is called autovivification.Any nonexistent variable,or a variable containing undef,which we dereference while looking for a variable location(technically called an lvalue context),is automatically stuffed with the appropriate reference to an empty item,and Perl allows the operation to proceed.
这一段是书上的原话,感觉说得实在是拗口的不得了,而且黑体字部分感觉上和实际的有矛盾,从黑体字来理解,对变量做解引用是为了获得变量的地址,而实际写程序时,对变量做解引用是为了获得地址是变量的值的数据的值(也挺拗口的,残念啊).
1. 对象:未定义的变量戒者值为undef的变量. 
2. 条件:对变量做解引用,即以变量的值位地址,并在左值.即是对地址为变量值的内存区域赋值. 
3. 结果:变量被自劢的赋值为右值数据的引用.(实际过程是,变量先被赋值为一个和右值
数据类型相同的空引用,然后再执行赋值操作——如果有赋值操作的话.)
  1. #!perl
  2. use strict;
  3. use 5.010;
  4. my $not_yet;
  5. say "$not_yet";
  6. say "@$not_yet";
  7. @$not_yet=(1,2,3);
  8. @$not_yet=(1,2,3);
程序第5行把$top当做一个复杂数据结构的引用使用. 
在程序执行完后,$top是一个引用,指向一个有3个元素(0~2)的数组,返个数组中的第三个元素(下标为2)也是一个引用,指向一个有5个元素的数组,其第5个元素(下标为4)的值为"lee- low".数组其他位置的元素的值都是undef.
阅读(349) | 评论(0) | 转发(0) |
0

上一篇:匿名哈希

下一篇:Referencing a Named Subroutine

给主人留下些什么吧!~~