Perl語言中Perl包和模塊詳盡解讀
Perl包和模塊
一、require函數(shù)
用require函數(shù)可以把程序分割成多個文件并創(chuàng)建函數(shù)庫。例如,在myfile.pl中有定義好的Perl函數(shù),可用語句require("myfile.pl");在程序中Perl包含進來。當Perl解釋器看到這一語句,就在內置數(shù)組變量@INC指定的目錄中尋找文件myfile.pl。如果找到了,該文件中的語句就被執(zhí)行,否則程序終止并輸出錯誤信息:
Can'tfindmyfile.plin@INC
作為子程序調用參數(shù),文件中最后一個表達式的值成為返回值,require函數(shù)查看其是否為零,若為零則終止。例如myfile.pl最后的語句是:
print("hello,world!\n");
$var=0;
因為最后的語句值為零,Perl解釋器輸出下列錯誤信息并推出:
myfile.pldidnotreturetruevalue
可以用簡單變量或數(shù)組元素等向require傳遞參數(shù),如:
- @reqlist=("file1.pl","file2.pl","file3.pl");
- require($reqlist[$0]);
- require($reqlist[$1]);
- require($reqlist[$2]);
還可以不指定文件名,即:
require;
這時,變量$_的值即作為文件名傳遞給require。
注:如果@INC中有多個目錄中含有同一個文件,則只有第一個被Perl包含。
1、require函數(shù)和子程序庫
用require函數(shù)可以創(chuàng)建可用于所有Perl程序的子程序庫,步驟如下:
a、確定存貯子程序庫的目錄
b、將子程序抽取放到單獨的文件中,將文件放到子程序庫目錄
c、每個文件末尾加一句非零值的語句,最簡單的辦法是語句1;
d、在主程序中用requirePerl包含一個或多個所需的文件。
e、運行主程序時,用-I選項指定子程序庫目錄,或者在調用require前將該目錄添加到@INC數(shù)組中。
例如:假設目錄/u/perldir中存有你的Perl子程序庫,子程序mysub存貯在文件mysub.pl中。現(xiàn)在來Perl包含上該文件:
unshift(@INC,"/u/perldir");
require("mysub.pl");
對unshift的調用把目錄/u/perldir添加到@INC數(shù)組,對require的調用將mysub.pl文件的內容Perl包含進來作為程序的一部分。
注意:
1、應該使用unshift來向@INC中添加目錄,而不是push。因為push增加到@INC的末尾,則該目錄將被最后搜尋。
2、如果你的庫文件名與/usr/local/lib/perl中的某文件同名,則不會被Perl包含進來,因為require只Perl包含同名文件中的第一個。
2、用require指定Perl版本
Perl5中,可以用require語句來指定程序運行所需的Perl版本。當Perl解釋器看到require后跟著數(shù)字時,則只有其版本高于或等于該數(shù)字時才運行該程序。例如,下面語句表明只有Perl解釋器為5.001版或更高時才運行該程序:
require5.001; #p#
二、Perl包
Perl程序把變量和子程序的名稱存貯到符號表中,perl的符號表中名字的集合就稱為Perl包(package)。
1、Perl包的定義
在一個程序中可以定義多個Perl包,每個Perl包有一個單獨的符號表,定義語法為:
packagemypack;
此語句定義一個名為mypack的Perl包,從此以后定義的所有變量和子程序的名字都存貯在該Perl包關聯(lián)的符號表中,直到遇到另一個package語句為止。
每個符號表有其自己的一組變量、子程序名,各組名字是不相關的,因此可以在不同的Perl包中使用相同的變量名,而代表的是不同的變量。如:
$var=14;
packagemypack;
$var=6;
第一個語句創(chuàng)建變量$var并存貯在main符號表中,第三個語句創(chuàng)建另一個同名變量$var并存貯在mypackPerl包的符號表中。
2、在Perl包間切換
在程序里可以隨時在Perl包間來回切換,如:
- 1:#!/usr/local/bin/perl
- 2:
- 3:packagepack1;
- 4:$var=26;
- 5:packagepack2;
- 6:$var=34;
- 7:packagepack1;
- 8:print("$var\n");
運行結果如下:
$program
26
$
第三行定義了Perl包pack1,第四行創(chuàng)建變量$var,存貯在Perl包pack1的符號表中,第五行定義新Perl包pack2,第六行創(chuàng)建另一個變量$var,存貯在Perl包pack2的符號表中。這樣就有兩個獨立的$var,分別存貯在不同的Perl包中。第七行又指定pack1為當前Perl包,因為Perl包pack1已經定義,這樣,所有變量和子程序的定義和調用都為該Perl包的符號表中存貯的名字。因此第八行對$var的調用為pack1Perl包中的$var,其值為26。
3、mainPerl包
存貯變量和子程序的名字的缺省符號表是與名為main的Perl包相關聯(lián)的。如果在程序里定義了其它的Perl包,當你想切換回去使用缺省的符號表,可以重新指定mainPerl包:
packagemain;
這樣,接下來的程序就好象從沒定義過Perl包一樣,變量和子程序的名字象通常那樣存貯。
4、Perl包的引用
在一個Perl包中可以引用其它Perl包中的變量或子程序,方法是在變量名前面加上Perl包名和一個單引號,如:
- packagemypack;
- $var=26;
- packagemain;
- print("$mypack'var\n");
這里,$mypack'var為mypackPerl包中的變量$var。
注意:在Perl5中,Perl包名和變量名用雙冒號隔開,即$mypack::var。單引號引用的方式仍然支持,但將來的版本中未必支持。
5、指定無當前Perl包
在Perl5中,可以用如下語句指定無當前Perl包:
package;
這時,所有的變量必須明確指出所屬Perl包名,否則就無效--錯誤。
$mypack::var=21;#ok
$var=21;#error-nocurrentpackage
這種情況直到用package語句指定當前Perl包為止。
6、Perl包和子程序
Perl包的定義影響到程序中的所有語句,Perl包括子程序,如:
- packagemypack;
- subroutinemysub{
- local($myvar);
- #stuffgoeshere
- }
這里,mysub和myvar都是Perl包mypack的一部分。在Perl包mypack外調用子程序mysub,則要指定Perl包:$mypack'mysub。
可以在子程序中切換Perl包:
packagepack1;
subroutinemysub{
$var1=1;
packagepack2;
$var1=2;
}
這段代碼創(chuàng)建了兩個變量$var1,一個在Perl包pack1中,一個在Perl包pack2中,Perl包中的局域變量只能在其定義的子程序等語句塊中使用,像普通的局域變量一樣。
7、用Perl包定義私有數(shù)據(jù)
Perl包最通常的用途是用在含有子程序和子程序所使用的全局變量的文件中,為子程序定義這樣的Perl包,可以保證子程序使用的全局變量不可在其它地方使用,這樣的數(shù)據(jù)即為私有數(shù)據(jù)。更進一步,可以保證Perl包名不可在其它地方使用。私有數(shù)據(jù)例:
- 1:packageprivpack;
- 2:$valtoprint=46;
- 3:
- 4:packagemain;
- 5:#Thisfunctionisthelinktotheoutsideworld.
- 6:subprintval{
- 7:&privpack'printval();
- 8:}
- 9:
- 10:packageprivpack;
- 11:subprintval{
- 12:print("$valtoprint\n");
- 13:}
- 14:
- 15:packagemain;
- 16:1;#returnvalueforrequire
此子程序只有在調用printval后才能產生輸出。
該文件分為兩個部分:與外界聯(lián)系的部分和私有部分。前者為缺省的mainPerl包,后者為Perl包privpack。第6~8行定義的子程序printval可被其它程序或子程序調用。printval輸出變量$valtoprint的值,此變量僅在Perl包privpack中定義和使用。第15、16行確保其被其它程序用require語句Perl包含后工作正常,15行將當前Perl包設置回缺省Perl包main,16行返回非零值使require不報錯。
8、Perl包和系統(tǒng)變量
下列變量即使從其它Perl包中調用,也在mainPerl包中起作用:
文件變量STDIN,STDOUT,STDERR和ARGV
變量%ENV,%INC,@INC,$ARGV和@ARGV
其它含有特殊字符的系統(tǒng)變量
9、訪問符號表
在程序中查找符號表可用數(shù)組%_package,此處package為想訪問的符號表所屬的Perl包名。例如%_main含有缺省的符號表。
通常不需要親自查找符號表。#p#
三、模塊
多數(shù)大型程序都分割成多個部件,每一部件通常含有一個或多個子程序及相關的變量,執(zhí)行特定的一個或多個任務。集合了變量和子程序的部件稱為程序模塊。
1、創(chuàng)建模塊
Perl5中用Perl包來創(chuàng)建模塊,方法是創(chuàng)建Perl包并將之存在同名的文件中。例如,名為Mymodult的Perl包存貯在文件Mymodult.pm中(擴展名.pm表示PerlModule)。下例的模塊Mymodult含有子程序myfunc1和myfunc2及變量$myvar1和$myvar2。
- 1:#!/usr/local/bin/perl
- 2:
- 3:packageMymodule;
- 4:requireExporter;
- 5:@ISA=qw(Exporter);
- 6:@EXPORT=qw(myfunc1myfunc2);
- 7:@EXPORT_OK=qw($myvar1$myvar2);
- 8:
- 9:submyfunc1{
- 10:$myvar1+=1;
- 11:}
- 12:
- 13:submyfunc2{
- 14:$myvar2+=2;
- 15:}
第3~7行是標準的Perl模塊定義方式。第3行定義Perl包,第4行Perl包含內置Perl模塊Exporter,6、7行進行子程序和變量的輸出以與外界聯(lián)系。第6行創(chuàng)建名為@EXPORT的特殊數(shù)組,該數(shù)組中的子程序可以被其它程序調用,這里,myfunc1和myfunc2可以被訪問。其它任何在模塊中定義但沒有賦給數(shù)組@EXPORT的子程序都是私有的,只能在模塊內部調用。第7行創(chuàng)建另一個名為@EXPORT_OK的特殊數(shù)組,其中含有可被外部程序訪問的變量,這里含有$myvar1和$myvar2。
2、導入模塊
將模塊導入你的Perl程序中使用use語句,如下句導入了Mymodule模塊:
useMymodule;
這樣,模塊Mymodule中的子程序和變量就可以使用了。
取消導入模塊使用no語句,如下句取消了Mymodule模塊的導入:
noMymodule;
下面看一個導入模塊和取消導入的例子,使用integer模塊要求所有數(shù)字運算基于整數(shù),浮點數(shù)在運算前均被轉化為整數(shù)。
- 1:#!/usr/local/bin/perl
- 2:
- 3:useinteger;
- 4:$result=2.4+2.4;
- 5:print("$result\n");
- 6:
- 7:nointeger;
- 8:$result=2.4+2.4;
- 9:print("$result\n");
程序輸出如下:
$program
4
4.8
$
如果use或no語句出現(xiàn)在語句塊中,則只在該塊的有效范圍內起作用,如:
- useinteger;
- $result1=2.4+2.4;
- if($result1==4){
- nointeger;
- $result2=3.4+3.4;
- }
$result3=4.4+4.4;
結果輸出如下:
4
6.8
8
這里,no語句只在if語句中有效,出了if語句仍使用integer模塊,因此4.4在做加法前被轉化成了4。
3、預定義模塊
Perl5提供了許多有用的預定義模塊,可以用use導入和no語句取消。下面是庫中最有用的一些模塊:
Perl文檔中有完整的預定義模塊列表。
注:世界各地的Perl5用戶寫了許多有用的模塊,CPAN(ComprehensivePerlArchiveNetwork)的Perl文檔有其完整的列表。關于CPAN的更多信息見其網址:http://www.perl.com/perl/CPAN/README.html。
【編輯推薦】
本文和大家重點討論一下Perl包和模塊的概念,多數(shù)大型程序都分割成多個部件,每一部件通常含有一個或多個子程序及相關的變量,執(zhí)行特定的一個或多個任務。集合了變量和子程序的部件稱為程序模塊。