《Beginning Perl》讀書筆記4:11~13章

來源:互聯網
上載者:User
第11章:引用
  • 引用一律聲明為標量類型(即$開頭的命名變數),使用\運算子取引用

    • 對引用變數的修改等同於對引用指向實際資料的修改
    • 取變數引用:my $scalar_r = \$scalar;
    • 取列表的引用:my $array_r = \@array;
    • 取雜湊的引用:my $hash_r = \%hash; 
  • 通過引用解決列表無法嵌套的問題:

 

my @array1 = (10, 20, 30, 40, 50);
my @array2 = ( 1, 2, \@array1, 3, 4);

 

  • 因為\@array1本質上只是一個標量,所以列表不會被扁平化,依舊保留了嵌套層次
  • 對匿名列表的引用:將列表的()替換為[]:my $array_r = [1, 2, 3, 4, 5];
  • 對匿名雜湊的引用:將雜湊的()替換為{}:my $hash_r = { apple => "pomme", pear => "poire" };
  • 對引用變數解引用通過{$var_r}實現
    • 列表

 

my @array = (1, 2, 3, 4, 5);
my $array_r = \@array;
my @array2 = @{$array_r};  #拷貝了數組

 

    • 雜湊與列表類似
  • 對於數組引用,可以將${$ref}簡記為$ref->,例如可以將${$ref}[2]簡記為$ref->[2],而將${${ref}[2]}[1]簡記為$ref->[2]->[1],並進一步簡記為$ref->[2][1]
  • 使用undef銷毀一個引用:undef $ref; perl對於引用指向的資料維護一個引用計數,當計數減到0時引用指向的資料被銷毀,記憶體空間被釋放
  • 使用引用使得表示複雜的資料結構成為可能。這些資料結構包括矩陣(多維陣列)、鏈表、樹、圖等。
  • 一些思考:C/C++的引用主要為了傳地址。與C/C++中的指標、引用不同的是,perl引用除了傳遞地址外,還是perl中將標量(scalar)、列表(list)、雜湊(hash)進行一般化(或者說統一)表示的機制,使用引用後,可以將標量、列表、雜湊均表示為標量(因為地址本質上是一個無符號整型數,這一點與C中的void*有些類似)。通過引用,就可以解決perl中無法儲存帶有嵌套層次的列表、無法表示複雜資料結構的問題。
第12章:模組 
  • 模組是一個perl原始碼檔案,與普通的.pl原始碼檔案相比,模組有如下兩個不同點:

    • 副檔名不是pl,而是pm(這一條並不是強制條件)
    • 最後有一句1;(或是return true;或是任何返回true值的語句)強制要求
  • do用於在perl代碼中的任意位置嵌入一個.pl指令碼或是.pm模組,文法是do “filename”;perl將會在@INC中的路徑下尋找filename
    • 如果在main.pl中執行do ‘inc.pl’;需要注意的是inc.pl中的代碼不能訪問main.pl中定義的lexical變數
  • require用於在perl代碼中的任意位置嵌入一個模組,文法是require “filename”;或require modulename;當使用require modulename;時,modulename形如module::submodule::subsubmodule,代表檔案./module/submodule/subsubmodule.pm
    • 與do不同,require只支援嵌入模組,因此require的檔案必須以返回true語句結束
    • 對於一個檔案只嵌入一次,即使寫了多條對同一檔案的require語句
  • use用於在perl代碼中的任一位置嵌入一個模組,文法是use modulename;modulename同require中的modulename
    • 與require不同,use在編譯前執行,也就是說,即使use中的模組寫在代碼中的最後一句,也會第一個執行

 

- do require use
支援 源碼 模組 模組 模組
文法 do ‘filename’; require ‘filename’;
require modulename;
use modulename;
處理次數 嵌入幾次,處理幾次 僅一次 僅一次
檔案不存在 跳過,不報錯 報錯 報錯
執行時間 運行時 運行時 編譯時間(最先處理)

 

  • @INC變數也是一個普通perl列表,可以更改,因此可以自行向其中添加路徑(使用unshift或者push)
  • 模組檔案的開頭應該聲明package packagename;packagename形如package::subpackage::subsubpackage,對於package::subpackage::subsubpackage中的函數sub1,調用方法是package::subpackage::subsubpackage::sub1
    • 注意package聲明的是模組名,而require和use使用的模組名實際上是路徑名,和模組名並不一樣,比如說有一個模組為./m1/test1.pm,其中的package聲明卻是package m1::test2;該包內包含一個函數sub1,則在main.pl中應該use/require m1::test1;而在調用時則應該寫m1::test2::sub1()
    • 當然,為了清晰、易管理,模組名和模組檔案名稱、路徑應該保持一致
  • 可以使用Exporter類簡化包內的函數調用寫法。沒有使用Exporter時,必須寫形如package::subpackage::subsubpackage::sub1的調用,過於囉嗦,而在寫包時繼承Exporter即可:

 

package Acme::Webserver::LoggerExporter;
# Acme/Webserver/LoggerExporter.pm
use strict;
use warnings;
# become an exporter and export the functions
use Exporter;
use base 'Exporter';
our @EXPORT = qw(open_log close_log write_log log_level);
則調用open_log時就可以將全寫調用:
Acme::Webserver::LoggerExporter::open_log()
改為簡寫調用:
open_log()

 

  • 也可以在use模組時聲明要匯入的模組:
use Data::Dumper qw(Dumper);
# 可以直接調用Dumper()
 幾個常用的包
  • Data::Dumper是將變數序列化為perl文法的字串的包,序列化列表和雜湊時非常方便
  • File::Find是一個遍曆檔案夾,對其中每一個檔案進行處理的函數,用法是File::Find::find(\&wanted, “/home/simon/”);
    • 首個參數wanted是一個回呼函數,對每個檔案應用。第二個參數是執行檔案夾
    • 每次執行回調時目前的目錄被切換為當前檔案所在的目錄
    • 目前的目錄的相對路徑為$File::Find::dir
    • $_為當前檔案的檔案名稱
    • $File::Find::name為當前檔案的全名(包括目錄)
  • Getopt::Std和Getopt::Long是兩個處理命令列參數的包,可以將形如-al的簡寫命令列參數解析為a和l兩個參數,也可以將-a arg1 -l arg2這樣的命令列參數解析為雜湊映射
  • File::Spec是一個處理路徑字串的包,包括路徑字串簡化、路徑疊加、路徑解析等
  • Benchmark是一個效能測試包,可將某一代碼塊重複執行若干次,測得績效參數
  • Win32是一個封裝了一些Win32 API的包,包括Win32::Sound、Win32::TieRegistry等
第13章:物件導向的Perl
  • perl中並沒有真正的“類”,所謂的類,其實是一個包
  • 要定義一個類,聲明一個package即可:package Person;
  • 類的建構函式固定取名為new,即sub new {...}
  • 初始化類對象通過$obj = new Person();或者$obj = Person->new();
  • 建構函式sub new要點:
    • 參數表的第一個參數(@_[0])是類名,第二個開始為調用建構函式時傳入的參數
    • 通過傳入雜湊實作類別似成員變數的功能
    • 產生對象引用後,必須使用bless()函數對引用的類型進行轉換
    • 最後一句必須返回產生的對象引用

 

#類定義
package Person;

sub new { #此時_@為(‘Person’, ‘name’, ‘Carl’, ‘gender’, ‘male’)
 $classname = shift; #獲得類名,此時$classname為’Person’, _@為(‘name’, ‘Carl’, ‘gender’, ‘male’)
 my $self = {@_}; #將傳入參數轉化為雜湊,$self為(‘name’=>’Carl’, ‘gender’=>’male’)
 bless $self, $classname #將引用$self轉化為$classname類型
 return $self; #返回的Person對象本身是一個雜湊,含有所有成員變數
}

#類使用
$person = Person->new(‘name’=>’Carl’, ‘gender’=>’male’);

 

  • Package內定義的變數為類變數,即靜態成員變數(static member variable),不能直接存取,必須定義訪問器(accessor, 即get/set函數)
  • 成員函數要點:
    • 名字以底線_開頭的成員函數為私人的
    • 函數的第一個參數(即@_[0])為對象引用,第二個參數開始為函數參數

 

#類定義
package Person;

sub new {...} #省略
sub _init {...} #私人函數
sub name {
 my $self = shift; #取調用對象引用
 my $name = shift; #取第二個參數
 $self->{name} = $name if defined $name; #如果傳入名字,則設定名字為傳入值
 return $self->{name}; #返回名字值
}

#類使用
$person = Person->new(‘name’=>’Carl’, ‘gender’=>’male’);
$person->name(‘Caesar’); #將名字設定為’Caesar’
print $person->name(), “\n”;  #列印名字,將列印’Caesar’

 

  • 對象的銷毀參照11章中引用指向資料的銷毀方法
後記

Perl給我留下深刻印象的地方:

  • 簡捷易用的文本I/O、Regex使Perl成為文本處理的利器
  • 提供眾多UNIX API,加上指令碼語言的靈活性,Perl適合進行UNIX系統管理

個人感覺Perl中的兩個痛點,也是Perl的敗筆:

  • 引用(Reference)

    • 列表自動一維化的機制莫名其妙。Perl中標量、列表和雜湊擁有各自不同的詞法標識($、@、%,列表、雜湊內容均使用(),列表取值使用[],雜湊使用{}),將其引用化後解引用又有一套各自不同的詞法,很容易弄暈
  • 物件導向(OO)
    • Perl中的OO機制有點半殘,單單是建構函式中必寫的幾行:
my $classname = shift;
my $self = {@_};
bless $self, $classname;
return $self;
    • 以及函數中第一句必寫的my $self = shift;就讓人十分討厭,重複性勞動。如果這真的是一門OO語言,這些工作應該由編譯器完成。
    • 根據Wikipedia上Perl頁面的介紹,OO是Perl 5中加入的新特性,這說明Perl最早並沒有被設計為一門OO程式設計語言,所以Perl 5中的OO特性可以看成是在過程式語言中進行的一種升級。比如每個函數第一句就必有的my $self = shift;就與C++中的this指標神似,只不過C++作為一種新語言革命得比較徹底,this指標是由編譯器自動提供的,不必手工擷取。與C++相比,Perl裡的OO更像是用C語言實現的OO,說到這裡,有空可以去看看《Object-oriented Programming with ANSI-C》,這本書講了用C語言實現OO特性的各個技術細節,“通過這本書你可以明白C++, Java, Python 等物件導向語言中的類、繼承、執行個體、串連、方法、對象、多態... 都是如何?的. 能讓你通過C來寫出優美並可以重用的代碼.”(以上文字來自豆瓣網友Border
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.