關(guān)于 Perl 與 Python 的起源和特點(diǎn)Perl 是 Practical Extraction and Report Language 的簡稱,由 1987 年 Larry Wall 創(chuàng)建,最初的目的是為了在 UNIX 上方便處理報(bào)表,經(jīng)過長期的發(fā)展已經(jīng)成為一種全功能的程序設(shè)計(jì)語言,當(dāng)前最新的版本為 Perl5.14.1,Perl 作為一種自由而強(qiáng)大的編程語言,其中心思想是: There's More Than One Way To Do It。(不只一種方法來做這件事 ),即「 Tim Toady 」。作為一種“膠水型”語言,它具有強(qiáng)大的正則表達(dá)式和模式匹配功能以及靈活的數(shù)據(jù)結(jié)構(gòu),如動(dòng)態(tài)數(shù)組、Hash 等,在語法規(guī)則上借鑒了 C/C++、Basic、Pascal 等語言,其不足之處在于存在一些冗余語法,代碼的可讀性較差。 Python 是一種基于面向?qū)ο蟮慕馕鲂越换ナ降拈_源編程語言,它起源于 1989 年末由 CWI(阿姆斯特丹國家數(shù)學(xué)和計(jì)算機(jī)科學(xué)研究所)的研究員 Guido van Rossum 創(chuàng)立,1991 年初公開發(fā)行,其開源式的發(fā)行方式促進(jìn)了 Python 的較快發(fā)展,目前已經(jīng)形成了一個(gè)強(qiáng)大的社區(qū)力量。Python 開發(fā)者的哲學(xué)是“用一種方法,最好是只有一種方法來做一件事”。Python 具有簡單易學(xué)、代碼規(guī)范、語法簡單、可移植性強(qiáng)、支持多平臺、類庫豐富等優(yōu)點(diǎn)。 Perl 與 Python 的基本數(shù)據(jù)類型腳本語言支持多種數(shù)據(jù)類型,變量無需事先申明,類型根據(jù)值來動(dòng)態(tài)確定,一個(gè)變量在程序中可以根據(jù)上下文環(huán)境的不同存儲(chǔ)不同類型的值。 Perl 支持的基本數(shù)據(jù)類型包括:標(biāo)量、數(shù)組、哈希。在定義的時(shí)分別用 $、@、% 表示。
Python 支持五種基本數(shù)據(jù)類型:數(shù)字 (Numbers)、字符串 (String)、列表 (List)、元組 (Tuple) 和字典 (Dictionary)。其中數(shù)字和字符串和 perl 中的標(biāo)量對應(yīng),列表和數(shù)組對應(yīng),元組可以看做是不可變的列表,字典和 hash 對應(yīng)。
Perl 與 Python 的控制結(jié)構(gòu)在控制結(jié)果方面,Perl 較 Python 豐富,除了支持傳統(tǒng)的 if 、while 、for 控制結(jié)構(gòu),還支持 until 、unless 、foreach 等,Python 的控制結(jié)構(gòu)相對要少一些,但已經(jīng)能夠滿足語言的要求。本節(jié)對這些控制結(jié)構(gòu)進(jìn)行詳細(xì)比較。 If 控制結(jié)構(gòu):Perl 與 Python 都支持 if 、if-else 、if-else if- else 三種結(jié)構(gòu),兩者在語法上基本類似,但與 Python 不同的是 Perl 中沒有 boolean 類型,零和空表示 False,其余表示 True,而 Python 中除了''、""、0、()、[]、{}、None 為 False 之外,其他的都是 True。同時(shí) Python 直接用縮進(jìn)表示 block 塊。 表 1. if 控制結(jié)構(gòu)
Perl 中還支持 unless 條件控制語句,基本語法如下: unless (expression) { unless 和 if 不同之處在于當(dāng)條件表達(dá)式的值為假的時(shí)候才執(zhí)行,同時(shí) unless 后面還能跟 else 語句。如: unless($mon =~/^Feb/){ print “This month has at least thirty days.\n”; }else{ print “Do you see what's going on here?\n”; } 循環(huán)控制結(jié)構(gòu):
Perl 中的 for 循環(huán)除了支持傳統(tǒng)的 for 循環(huán),即 for ( 表達(dá)式 1; 表達(dá)式 2; 表達(dá)式 3) ,還支持 foreach 語句,基本語法為: foreach $i (@aList) { stmt_1; } python 不支持傳統(tǒng)的 for 循環(huán),但是提供了強(qiáng)大的循環(huán)結(jié)構(gòu)可以遍歷序列成員,同時(shí) for 循環(huán)后面也可以接 else 語句,基本語法如下: for inter_var in iterable: suite_to_repeat else: else_statement
Perl 循環(huán)控制結(jié)果還支持 while 和 do-while 以及 until 形式,until 與 while 結(jié)構(gòu)相似,區(qū)別在于 unitl 會(huì)在條件為假的時(shí)候重復(fù)執(zhí)行。until 語法如下: until(expression) { statement; } 而 python 只支持 while 形式,但 python 可以在 while 后面接 else 語句。語法如下: While condition: statements else: statements 循環(huán)控制符Perl 有三個(gè)循環(huán)控制操作符,分別為 Last 、next 、redo。
Python 也有三個(gè)循環(huán)控制操作符,分別為 break 、continue 、pass 語句。
Perl 與 Python 的函數(shù)Perl 和 Python 都支持函數(shù),可以傳遞參數(shù)以及在程序中對函數(shù)進(jìn)行調(diào)用等。下面從函數(shù)的定義,調(diào)用,返回值以及參數(shù)傳遞等方面對這兩者進(jìn)行比較。
Perl 與 Python 的包與模塊Perl 程序把變量和子程序的名稱存貯到符號表中,Perl 的符號表中名字的集合就稱為 Perl 包 (package)。定義語法為:package mypack;每個(gè)符號表有其自己的一組變量、子程序名,各組名字是不相關(guān)的,因此可以在不同的 Perl 包中使用相同的變量名,而代表的是不同的變量。Perl 模塊有兩種來源,一種是隨 Perl 發(fā)行版本一同打包的,另外就是用 CPAN 中下載的。Perl 模塊和包的概念并不清晰,兩者有時(shí)可以混用。在程序中使用模塊的操作稱為導(dǎo)入模塊;導(dǎo)入模塊關(guān)鍵字 use;如:use ModuleName;模塊被導(dǎo)入后,其中的子程序和變量就可以直接使用了;要取消一個(gè)已經(jīng)導(dǎo)入了的模塊,可以使用關(guān)鍵字 no;如:no ModuleName。 一個(gè) .py 文件就是一個(gè) python 模塊。把一堆相關(guān)的 python 模塊放在一個(gè)目錄下,再加上一個(gè) __init__.py 文件就構(gòu)成了一個(gè) python 包。在 Python 另一個(gè)程序中導(dǎo)入模塊用 import module 或者 from module import *,兩者的區(qū)別在于:import module 會(huì)導(dǎo)入 module 這個(gè)模塊里的所有標(biāo)識,但是這些標(biāo)識現(xiàn)在都在 module 名字空間下。from module import * 也會(huì)導(dǎo)入 module 中所有標(biāo)識,但是標(biāo)識放到在當(dāng)前名字空間里。 導(dǎo)入模塊或包按下面順序進(jìn)行路徑查找: Perl 與 Python 中的 OOP在 Perl 中,類是 Perl 包,含有提供對象方法的類,而方法是 Perl 的子程序,類名是其第一個(gè)參數(shù),對象是對類中數(shù)據(jù)項(xiàng)的引用。在 Perl 中創(chuàng)建一個(gè)新類,首先要?jiǎng)?chuàng)建一個(gè)包,擴(kuò)展名為 .pm, 在創(chuàng)建 perl 包的時(shí)候程序的最后一個(gè)必須為"1;";否則該包不會(huì)被 Perl 處理。 清單 1. 創(chuàng)建 perl 的類和對象package person; use strict; sub new { my $class = shift(); print("CLASS = $class\n"); my $self = {}; $self->{"name"} = shift(); $self->{"sex"} = shift(); bless $self, $class; return $self; } 1; 其中 new() 方法是對象的構(gòu)造函數(shù),是創(chuàng)建該類的對象實(shí)例必須被調(diào)用的,它返回該對象的引用。將類名與引用相結(jié)合稱為”bless”一個(gè)對象,其語法為:bless YeReference [,classname] YeReference 是對被”祝?!钡膶ο蟮囊?,classname 是可選項(xiàng),指定對象獲取方法的包名,其缺省值為當(dāng)前包名。也可以通過函數(shù) bless 來聲明一個(gè)構(gòu)造函數(shù)。 sub new { my $class = shift; my $self = {}; bless $self, $class; return $self; } 創(chuàng)建一個(gè)對象可以直接使用 new 關(guān)鍵字。$object = new Person( "mohand", "sam", 345); Perl 類中的方法就 Perl 的子函數(shù),規(guī)定第一個(gè)參數(shù)為對象或者被引用的包,分為靜態(tài)方法和虛方法。 虛方法通常首先把第一個(gè)參數(shù) shift 到變量 self 或 this 中,然后將該值作普通的引用使用。一是通過該對象的引用 ( 虛方法 ),一是直接使用類名 ( 靜態(tài)方法 )。如上例中如果類 Person 中有 getContactList 則可以直接使用 $object->getContactList() 來調(diào)用該方法。 Perl 支持重載,當(dāng)兩個(gè)不同的類中含有相同的方法名稱的時(shí)候,可以用 :: 操作符指定使用哪個(gè)類中的方法。 由于 Perl 采用了簡單的、基于引用的垃圾回收系統(tǒng)。Perl 跟蹤對象的鏈接數(shù)目,當(dāng)某對象的最后一個(gè)應(yīng)用釋放到內(nèi)存池時(shí),該對象就自動(dòng)銷毀。因此一般不需要定義類的析構(gòu)函數(shù)。 Perl 通過數(shù)組 @ISA 支持繼承。 package Employee; use Person; use strict; our @ISA = qw(Person); # inherits from Person 當(dāng)子類繼承父類的時(shí)候,繼承了父類的所有方法,但子類也可以覆蓋父類的方法。如加入 Employee 想覆蓋父類的 getFirstName: #!/usr/bin/perl package Employee; use Person; use strict; our @ISA = qw(Person); # inherits from Person # Override helper function sub getFirstName { my( $self ) = @_; # This is child class function. print "This is child class helper function\n"; return $self->{_firstName}; } 1; 調(diào)用直接使用 $firstName = $object->getFirstName(); 如果要調(diào)用父類的 getFirstName,則可以使用 $object->Person::getFirstName(); 在 Python 中創(chuàng)建一個(gè)類的基本語法為 : class className(bases): classBody 參數(shù) base 可以是一個(gè)單繼承或者多繼承的父類,object 是所有類的父類,位于類繼承結(jié)構(gòu)的最上層。類的構(gòu)造函數(shù)為 __init__(),其中構(gòu)造函數(shù)中 self 會(huì)作為第一個(gè)默認(rèn)的參數(shù)。而類的析構(gòu)函數(shù)則是 __del__(),訪問類的方法和屬性可以直接使用 . 訪問符。 Python 不支持純虛函數(shù)或抽象方法,并且聲明和定義沒有本質(zhì)區(qū)別。一般或者 Python 類的屬性可以通過 __dict__ 或者 dict()訪問。常見屬性有 __name__ ,__doc__,__base__,__dict__。Python 中創(chuàng)建一個(gè)類的實(shí)例,不需要關(guān)鍵之 new,直接使用類名 () 即可。如 c=myclass()。 Python 不僅僅支持單繼承和多繼承,同時(shí)還支持方法的覆蓋 . class P(object): def foo(self): print 'Hi, I am P-foo()' >>> p = P() >>> p.foo() Hi, I am P-foo() 現(xiàn)在創(chuàng)建 C 類 , 繼承于 P class C(P): def foo(self): print 'Hi, I am C-foo()' >>> c = C() >>> c.foo() Hi, I am C-foo() 當(dāng)從一個(gè)帶構(gòu)造器 __init()_ 的類派生,如果在子類中覆蓋了 __init__(),當(dāng)子類被實(shí)例化時(shí),基類的 __init__() 方法不會(huì)被自動(dòng)調(diào)用。如果必須調(diào)用基類的構(gòu)造方法,可以使用父類名 .__init__(self) 方法或者 super( 子類名,self).__init__()。 如 def __init__(self): super(C, self).__init__() print "calling C's constructor" Python 類和實(shí)例支持一些內(nèi)建函數(shù),如 Issubclass(sub,sup):判斷一個(gè)類是另一個(gè)類的子類或子孫類; isinstance(obj1,obj2):判定一個(gè)對象是否是另一個(gè)給定類的實(shí)例; Perl 與 Python 的正則表達(dá)式正則表達(dá)式是 perl 比較突出的一大特色,perl 中正則表達(dá)式有三種形式: 轉(zhuǎn)換:tr/<charClass>/<substituteClass>/ 這種形式包含一系列的字符— /<charClass> —同時(shí)把它們替換為 <substituteClass>。 表 3. Perl 常用匹配模式
表 4. Python 常用匹配模式
Perl 與 Python 中的線程線程是一個(gè)單一的執(zhí)行流程,它是所有程序執(zhí)行過程中最小的控制單位,即能被 CPU 所調(diào)度的最小任務(wù)單元。在 Perl 中一個(gè)線程的生命周期包括創(chuàng)建,運(yùn)行與退出這三個(gè)階段。線程的運(yùn)行過程與普通函數(shù)的執(zhí)行類似,但新建線程的執(zhí)行與當(dāng)前線程的執(zhí)行是并行的。 在 Perl 中創(chuàng)建線程有兩種方法: 清單 2. 使用 threads 包的 create() 方法use threads; sub say_hello { printf("Hello thread! @_.\n"); return( rand(10) ); } my $t1 = threads->create( \&say_hello, "param1", "param2" ); 清單 3. 使用 async{} 塊創(chuàng)建線程#!/usr/bin/perl use threads; my $t4 = async{ printf("Hello thread!\n"); }; 對于線程的執(zhí)行控制,有兩種方式,一種是 join(),一種是 detach()。所謂 join() 就是在主線程中等待子線程的執(zhí)行返回值,然后再繼續(xù)執(zhí)行后續(xù)代碼,而在調(diào)用線程的 join() 方法之前,子線程與主線程的執(zhí)行是分開的。而 detach() 則是告訴解釋器主線程不關(guān)心子線程的執(zhí)行結(jié)果,所以該子線程在完成任務(wù)之后就是自動(dòng)退出,同時(shí)釋放自己所占有的資源,而不用主線程再操心。 Perl 默認(rèn)任何數(shù)據(jù)結(jié)構(gòu)都不是共享的,任何新創(chuàng)建的線程都有當(dāng)前數(shù)據(jù)的私有拷貝。如果要共享數(shù)據(jù),必須使用 threads::shard 進(jìn)行顯示聲明。 如: my $var :shared = 0; # use :share tag to define my @array :shared = (); # use :share tag to define my %hash = (); share(%hash); # use share() funtion to define 同時(shí) Perl 線程還支持鎖機(jī)制,可以使用 lock 方法實(shí)現(xiàn)線程間共享數(shù)據(jù)的鎖機(jī)制。Perl 中的 Thread::Semaphore 包為線程提供了信號量的支持,Thread::Queue 包為線程提供了線程安全的隊(duì)列支持。更多使用讀者可以自行查閱相關(guān)文檔。 Python 提供了幾個(gè)用于多線程編程的模塊,包括 thread, threading 和 Queue 等。thread 和 threading 模塊允許程序員創(chuàng)建和管理線程。thread 模塊提供了基本的線程和鎖的支持,而 threading 提供了更高級別,功能更強(qiáng)的線程管理的功能。Queue 模塊允許用戶創(chuàng)建一個(gè)可以用于多個(gè)線程之間共享數(shù)據(jù)的隊(duì)列數(shù)據(jù)結(jié)構(gòu)。 Python 的線程創(chuàng)建也有兩種方式,一是利用 thread 模塊的 start_new_thread() 函數(shù)來產(chǎn)生新線程。 import time import thread def timer(no, interval): cnt = 0 while cnt<10: print 'Thread:(%d) Time:%s/n'%(no, time.ctime()) time.sleep(interval) cnt+=1 thread.exit_thread() def test(): #Use thread.start_new_thread() to create 2 new threads thread.start_new_thread(timer, (1,1)) thread.start_new_thread(timer, (2,2)) if __name__=='__main__': test() 另一種是創(chuàng)建 threading.Thread 的子類來包裝一個(gè)線程對象。 class timer(threading.Thread): # derived from the class threading.Thread def __init__(self, num, interval): threading.Thread.__init__(self) self.thread_num = num self.interval = interval self.thread_stop = False def run(self): #Overwrite run() method, put what you want the thread do here while not self.thread_stop: print 'Thread Object(%d), Time:%s/n' %(self.thread_num, time.ctime()) time.sleep(self.interval) def stop(self): self.thread_stop = True Python 線程中也提供同步機(jī)制,可以利用 thrading 模塊的 threading.RLock 和 hreading.Condition 可以分別實(shí)現(xiàn)鎖機(jī)制和條件變量。 其中 acquire() 和 release() 方法分別獲取和釋放鎖。 def run(self): global x lock.acquire() for i in range(3): x = x + 1 time.sleep(2) print x lock.release() 更多關(guān)于線程的內(nèi)容,讀者可查閱相關(guān)文檔。 總結(jié)本文從 Perl 和 Python 的起源,基本數(shù)據(jù)類型、控制結(jié)構(gòu)、函數(shù)、包與模塊、面向?qū)ο蟆⒄齽t表達(dá)式以及線程等方面進(jìn)行了比較,從而給需要同時(shí)掌握這兩種腳本語言的開發(fā)人員一定參考,以便更好的理解與應(yīng)用。 |
|