Python 語(yǔ)言淺議
摘要:Python是面向?qū)ο蟮哪_本語(yǔ)言,具有很多現(xiàn)代語(yǔ)言的優(yōu)秀特征;本文簡(jiǎn)要介紹Python語(yǔ)言的某些特性,應(yīng)用領(lǐng)域,設(shè)計(jì)哲學(xué),并與其它語(yǔ)言做簡(jiǎn)單對(duì)比。
注:筆者使用的Python版本是
關(guān)鍵字:腳本語(yǔ)言(scripting language) 動(dòng)態(tài)語(yǔ)言(Dynamic Programming Language)、內(nèi)省(Introspection)、垃圾收集(Garbage Collection)
”There is only one way to do it, the right way”
-------Guido van Rossum
Python的歷史
Python的創(chuàng)始人是Guido van Rossum,在發(fā)明Python語(yǔ)言之前Guido曾參與過(guò)一門(mén)稱作ABC的語(yǔ)言的設(shè)計(jì),ABC是專門(mén)為非專業(yè)程序員設(shè)計(jì)的;Guido在Python語(yǔ)言的設(shè)計(jì)過(guò)程中吸收了ABC語(yǔ)言的許多優(yōu)點(diǎn),諸如ABC的數(shù)據(jù)類型(列表、元組、文本等),變量無(wú)需聲明,內(nèi)建的功能強(qiáng)大的字符串處理以及簡(jiǎn)單的控制結(jié)構(gòu)等特性;同時(shí)摒棄了ABC語(yǔ)言的一些缺陷,其中最主要的就是使Python更易擴(kuò)展,這也是Python語(yǔ)言現(xiàn)在如此流行的原因之一。Python的第一個(gè)實(shí)現(xiàn)是在mac機(jī)上,Python語(yǔ)言的設(shè)計(jì)還受到Modula-3(另一種優(yōu)美強(qiáng)大的語(yǔ)言)的影響,并結(jié)合了Unix Shell和C的習(xí)慣。現(xiàn)在Python是OpenSource的項(xiàng)目,同時(shí)Python社區(qū)非常的活躍,極大促進(jìn)了Python語(yǔ)言的發(fā)展。目前Python語(yǔ)言最新的版本是
Python的特性
Python是面向?qū)ο蟮?,跨平臺(tái)的,可擴(kuò)展的解釋型通用編程語(yǔ)言,它支持模塊和包;Python的代碼類型有三種:.py .pyc .pyo,分別是字節(jié)代碼,二進(jìn)制代碼,優(yōu)化代碼,都可以直接運(yùn)行,無(wú)需編譯或者鏈接的步驟,而且Python還提供交互執(zhí)行環(huán)境;Python是動(dòng)態(tài)類型語(yǔ)言,不需要類型聲明;提供自動(dòng)內(nèi)存管理;內(nèi)置高級(jí)數(shù)據(jù)類型和操作支持;Python可擴(kuò)展,可嵌入;語(yǔ)法簡(jiǎn)單清晰,強(qiáng)調(diào)代碼可讀性;可動(dòng)態(tài)加載C模塊;可動(dòng)態(tài)裝載Python模塊;Python屬動(dòng)態(tài)語(yǔ)言,允許在程序運(yùn)行期間動(dòng)態(tài)添加刪除函數(shù),對(duì)類和實(shí)例可以在運(yùn)行時(shí)動(dòng)態(tài)添加修改方法;Python是具有內(nèi)省性的語(yǔ)言;提供標(biāo)準(zhǔn)的GUI框架開(kāi)發(fā)圖形界面程序;支持標(biāo)準(zhǔn)Internet協(xié)議;支持內(nèi)建的和第三方提供的庫(kù),豐富的庫(kù)支持;免費(fèi)使用且完全開(kāi)放源代碼。
Python語(yǔ)法
Python語(yǔ)言中一切事物都是對(duì)象,例如如下一個(gè)看似普通的字符串:
>>> 'tool.txt'.find('oo')
1
內(nèi)置在Python中的簡(jiǎn)單數(shù)據(jù)類型有:
bool int long float complex
Python內(nèi)置容器類包含:
str unicode set frozenset list tuple dict
其中str unicode list tuple都支持訪問(wèn)給定順序的對(duì)象,dict是一個(gè)映射
str unicode tuple frozenset這四個(gè)容器類一旦創(chuàng)建了,就不能更改它們所存儲(chǔ)的數(shù)據(jù)了;list dict set是可變?nèi)萜鳌?/span>
除了這些內(nèi)置高級(jí)數(shù)據(jù)類型,程序員還可以通過(guò)擴(kuò)展模塊自定義內(nèi)置數(shù)據(jù)類型以支持實(shí)際應(yīng)用;Python屬動(dòng)態(tài)類型語(yǔ)言,這是大部分腳本語(yǔ)言的特性:通過(guò)賦值決定或改變變量類型;Python使用縮排標(biāo)識(shí)程序塊結(jié)構(gòu),這是Python的一大特色,減少了不必要的塊包圍符號(hào);str、unicode、list、tuple等類可以通過(guò)乘法實(shí)現(xiàn)多個(gè)容器的組合,可以通過(guò)分片進(jìn)行分割,還能夠負(fù)索引表示從后向前查找;可進(jìn)行連續(xù)比較:x<y<8;可同時(shí)賦值:x,y,z = 1, 2, 3,甚至x, y = y, x。
Python內(nèi)省性
內(nèi)?。?/span>Introspection)是一個(gè)運(yùn)行時(shí)動(dòng)態(tài)發(fā)現(xiàn)對(duì)象信息的能力:檢查某些事物以確定它是什么,它知道什么,它能做什么。Python提供了深入而全面的內(nèi)省支持,提高了Python語(yǔ)言的靈活性和可控性。另一個(gè)相似的概念是Java語(yǔ)言里的反射(Reflection),Java程序可以在運(yùn)行時(shí)加載、查探、使用編譯期間未知的classes。Reflection和Introspection是經(jīng)常相提并論的兩個(gè)術(shù)語(yǔ)。下面舉幾個(gè)例子說(shuō)明Python的內(nèi)省機(jī)制
dir()
函數(shù)是 Python 內(nèi)省機(jī)制中比較有名的一部分。它返回傳遞給它的任何對(duì)象的屬性名稱經(jīng)過(guò)排序的列表。舉個(gè)例子:
>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
type()函數(shù)可以幫助程序員確定對(duì)象的類型:
>>> type([])
<type 'list'>
>>>import sys
>>> type(sys)
<type 'module'>
>>> type(dir)
<type 'builtin_function_or_method'>
hasattr()函數(shù)和getattr()函數(shù)檢索一個(gè)對(duì)象擁有的屬性
>>> import os
>>> hasattr(os.dup, '__doc__')
True
>>> print getattr(os.dup, '__doc__')
dup(fd) -> fd2
Return a duplicate of a file descriptor.
callable()
函數(shù)測(cè)試對(duì)象的可調(diào)用性:
>>> callable('string')
False
>>> callable(callable)
True
Python內(nèi)存管理
Python不提供顯式的內(nèi)存分配回收API,完全自動(dòng)的內(nèi)存管理;Python memory manager實(shí)現(xiàn)了對(duì)程序運(yùn)行時(shí)堆的管理,包括內(nèi)存的分配,垃圾回收機(jī)制等;垃圾回收(garbage collection,一下簡(jiǎn)稱GC)在當(dāng)前的版本中使用的是引用計(jì)數(shù)垃圾收集和可選的循環(huán)結(jié)構(gòu)垃圾空間掃描技術(shù),一旦對(duì)象變得‘不可達(dá)’的時(shí)候就會(huì)被回收,但是不保證能夠回收包含循環(huán)引用計(jì)數(shù)的內(nèi)存垃圾。引用計(jì)數(shù)的算法比較直觀:在每個(gè)存儲(chǔ)片中記錄了指向其的指針數(shù)目;在對(duì)存儲(chǔ)片進(jìn)行某些操作時(shí),對(duì)引用計(jì)數(shù)進(jìn)行更新,分配一個(gè)存儲(chǔ)片時(shí)引用計(jì)數(shù)初始化為1,只要存儲(chǔ)片的引用被復(fù)制,引用計(jì)數(shù)加1,存儲(chǔ)片的引用被刪除時(shí),引用計(jì)數(shù)減1,如果引用計(jì)數(shù)減為0,則存儲(chǔ)片會(huì)由于不可達(dá)而被回收。很明顯引用計(jì)數(shù)算法不能回收循環(huán)的數(shù)據(jù)結(jié)構(gòu);設(shè)想一個(gè)簡(jiǎn)單的場(chǎng)景:對(duì)象a一個(gè)成員指向?qū)ο?/span>b,同時(shí)b也有一個(gè)成員指向a,而且代碼中只有引用a的部分,b對(duì)象只是輔助a對(duì)象而生成的,如果后來(lái)a對(duì)象被刪除了,那么a和b作為一個(gè)整體都變成內(nèi)存垃圾了,理論上應(yīng)該都被內(nèi)存管理器刪除,但是由于引用計(jì)數(shù)算法每次只考察一個(gè)結(jié)點(diǎn),因此對(duì)于循環(huán)的數(shù)據(jù)結(jié)構(gòu)無(wú)法回收。所以在編程時(shí)應(yīng)盡量避免循環(huán)引用的情況出現(xiàn)。
Python的動(dòng)態(tài)性掠影
Python是動(dòng)態(tài)語(yǔ)言,所謂動(dòng)態(tài)語(yǔ)言(Dynamic Programming Language),現(xiàn)在大致認(rèn)同的一個(gè)定義是:程序運(yùn)行期間允許改變程序結(jié)構(gòu)或者變量類型。
def change_method(klass, method_name, replacement):
'change a method using a replacement method'
setattr(klass, method_name, new.instancemethod(replacement, None, klass))
def changed(self, *args, **kwds):
print 'args: %s, kwds: %s, nothing' % (args, kwds)
def demo( ):
class Test:
def fun(self, ran):
print 'This is a method_change test %s' % ran
d = Test( )
d.fun('hehe')
change_method(Test, 'fun', changed)
d.fun('haha')
demo( )
程序輸出如下:
This is a method_change test hehe
args: ('haha',), kwds: {}, nothing
可以看到Test類的fun方法在程序運(yùn)行期間發(fā)生了改變。
稍稍解釋一下程序代碼:setattr(object, name, value)函數(shù)的功能是用來(lái)改變object類的name屬性值為value;這里就是改變Test類的fun方法為一個(gè)新的方法replacement,instancemethod(function, instance, class)函數(shù)返回一個(gè)方法對(duì)象,注意在python里一切皆對(duì)象;可見(jiàn)setattr(…)一個(gè)語(yǔ)句就把Test類的fun方法替換成為changed函數(shù)了,體現(xiàn)了python的簡(jiǎn)單強(qiáng)大。
Python語(yǔ)言和其它語(yǔ)言的比較
Python語(yǔ)言的執(zhí)行效率跟C/C++/Java比起來(lái)要稍遜一籌,但是代碼長(zhǎng)度大大縮短,并且Python跨平臺(tái)、類庫(kù)豐富、語(yǔ)法簡(jiǎn)單、開(kāi)發(fā)速度快,因此常用Python代替C/Java構(gòu)建大程序,涉及到系統(tǒng)效率的地方可以考慮用C/C++實(shí)現(xiàn)。而且Python也可以做glue language(膠水語(yǔ)言),因?yàn)?/span>Python跟C和Java的溝通能力非常的好。
三大腳本語(yǔ)言的比較:Perl Python Tcl
Perl原是專門(mén)設(shè)計(jì)處理文本的,這方面能力最強(qiáng),但是不適合編寫(xiě)大程序,語(yǔ)法晦澀難懂,與之相比,Python更易閱讀,學(xué)習(xí),可維護(hù)性更強(qiáng),代碼安全性更好(Python的異常處理),并且與Java語(yǔ)言更好的集成能力;Tcl的語(yǔ)法簡(jiǎn)單,和其它程序的交互能力強(qiáng),可以和C語(yǔ)言集成,而且有tk輔助GUI開(kāi)發(fā),但是Tcl更多是作為scripting language和glue language,不適合寫(xiě)大程序,與之相比Python的應(yīng)用范圍要廣闊的多。
Ruby:Python的正則表達(dá)式?jīng)]有Ruby的用著方便,Ruby比Python有更完整的面向?qū)ο蟮恼Z(yǔ)法,Ruby的主要功能都是用類的方法調(diào)用來(lái)實(shí)現(xiàn)的,不是函數(shù);另一方面由于Ruby的強(qiáng)大,語(yǔ)言相對(duì)Python復(fù)雜,Ruby沒(méi)有內(nèi)省性,缺乏國(guó)際化支持,缺乏類似Jython的東西。
Python的實(shí)現(xiàn)
CPython 通常的Python,完全用C語(yǔ)言實(shí)現(xiàn)的最原始的版本
Jython Python的純Java實(shí)現(xiàn);它可以將Python源代碼翻譯成Java字節(jié)碼,在Java虛擬機(jī)上運(yùn)行,是與Java的最無(wú)縫最平滑的集成;而且用戶可以從Python訪問(wèn)所有Java庫(kù)、構(gòu)建Applet、與Java Bean集成等
Python for .NET
.NET平臺(tái)上實(shí)現(xiàn)的Python;確切的說(shuō)Python for .NET是一種編譯器和運(yùn)行時(shí);它將 Python 腳本編譯成外部虛擬機(jī)的格式,并使得.NET類庫(kù)在Python語(yǔ)言中可用
IronPython .NET平臺(tái)上的Python;相對(duì)于傳統(tǒng)的Python,IronPython支持可選的靜態(tài)編譯功能,靜態(tài)編譯過(guò)的IronPython程序就形成了常規(guī)的.NET可執(zhí)行文件(.EXE文件)。甚至還可以將IronPython程序靜態(tài)編譯為.NET動(dòng)態(tài)鏈接庫(kù)(.dll文件)并且供C#和VB.NET等.NET語(yǔ)言調(diào)用
PyPy 用Python寫(xiě)的Python環(huán)境,很有趣
Python的應(yīng)用
Python自身的優(yōu)秀特性決定了其在實(shí)際應(yīng)用中的廣泛性。快速原型開(kāi)發(fā);網(wǎng)絡(luò)服務(wù)器腳本;科學(xué)計(jì)算;文檔處理;數(shù)據(jù)庫(kù)編程;嵌入開(kāi)發(fā);GUI開(kāi)發(fā);游戲開(kāi)發(fā);移動(dòng)開(kāi)發(fā)......Python擁有強(qiáng)大Python社區(qū)的支持,豐富的類庫(kù),以及C/C++/Java等語(yǔ)言提供可擴(kuò)展模塊。
全球已經(jīng)有很多公司和政府使用Python進(jìn)行企業(yè)級(jí)的軟件開(kāi)發(fā)和應(yīng)用,比如Google
"Python has been an important part of Google since the beginning, and remains so as the system grows and evolves. Today dozens of Google engineers use Python, and we're looking for more people with skills in this language."
―――Peter Norvig, director of search quality at Google, Inc.
除了Google,還有NASA,NYSE,Yahoo!,RealNetworks,RedHat,LLNL,Fermilab,Zope Corporation,Alice project at CMU,Infoseek等等
Python的哲學(xué)(Pythonic)
在Python交互環(huán)境中輸入”import this”,可以看到Python語(yǔ)言的設(shè)計(jì)哲學(xué):
>>>import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
與Perl語(yǔ)言不同,Python力求精簡(jiǎn),Perl會(huì)提供給程序員很多種解決問(wèn)題的方式,語(yǔ)言的泛化更強(qiáng),但是Python則會(huì)在泛化、簡(jiǎn)單性和性能等方面作出權(quán)衡,力求給出一個(gè)最佳方案。
”The underlying idea that there should preferably be ONE obvious way to express a solution is part of what has kept Python so great as it evolved during the years.”
腳本語(yǔ)言
摩爾定律斷言了處理器、內(nèi)存或者I/O設(shè)備等將不再大幅度影響程序的執(zhí)行效率,對(duì)于相當(dāng)一部分的應(yīng)用程序而言,實(shí)現(xiàn)同樣的功能,用系統(tǒng)語(yǔ)言和腳本語(yǔ)言相比,生成代碼的運(yùn)行效率可能都會(huì)在可容忍的范圍內(nèi),但是腳本語(yǔ)言代碼量可能會(huì)低很多(Python和Java大約是1:6),開(kāi)發(fā)周期更短,而且現(xiàn)在很多常用的功能都已經(jīng)用系統(tǒng)語(yǔ)言實(shí)現(xiàn)了,可以作為功能模塊,配合腳本語(yǔ)言的glue功能,即可完成系統(tǒng)實(shí)現(xiàn)。
一般來(lái)說(shuō)腳本語(yǔ)言的學(xué)習(xí)相比系統(tǒng)編程語(yǔ)言而言要更容易些,因?yàn)橄到y(tǒng)語(yǔ)言(如C/C++/Java)功能更加強(qiáng)大,語(yǔ)言復(fù)雜性高,學(xué)習(xí)周期長(zhǎng);從某種意義上說(shuō),腳本語(yǔ)言一句指令可以做更多事,更加人性化,體現(xiàn)了機(jī)器為人服務(wù)的宗旨。因?yàn)橐粋€(gè)程序如果人做的少了,機(jī)器就相應(yīng)做的多了,正好符合自動(dòng)化的思想,發(fā)明機(jī)器就是為了要減輕人的勞動(dòng)。腳本語(yǔ)言從這個(gè)角度來(lái)說(shuō)是值得大力推崇的。但是沒(méi)有什么是完美的,讓機(jī)器做的太多的代價(jià)很有可能就是不如讓機(jī)器做的少運(yùn)行效率高。比如Python運(yùn)行時(shí)要做動(dòng)態(tài)的類型檢查,要耗費(fèi)機(jī)器運(yùn)行時(shí)間,在C等靜態(tài)編譯的語(yǔ)言中這個(gè)工作是留給人做了,還有一些類似的因素,因此C的效率比Python高很多。
腳本語(yǔ)言有其與生俱來(lái)的優(yōu)點(diǎn),但是優(yōu)點(diǎn)也決定了缺點(diǎn)。類似的,各種語(yǔ)言之間都互有差異,語(yǔ)言只是工具,要根據(jù)任務(wù)的不同選擇不同的工具。比如要文本處理就使用Perl或Awk,使用Zope就用Python,做專家系統(tǒng)就用Prolog,要跟操作系統(tǒng)底層交互就用C,跨平臺(tái)就用Java或Python。
總結(jié)
Python最大特點(diǎn):簡(jiǎn)單易用優(yōu)美強(qiáng)大。簡(jiǎn)單性是Python語(yǔ)言最核心的設(shè)計(jì)哲學(xué),例如Python的很多功能都是以擴(kuò)展模塊的形式提供的,Python的內(nèi)核很小巧,語(yǔ)法簡(jiǎn)單,很容易學(xué)習(xí);Python強(qiáng)調(diào)代碼的可讀性,以縮排的方式省去冗余,代碼給人的感覺(jué)很清爽、美觀;程序以模塊和包的形式分發(fā),版本可控性強(qiáng);Python編譯成的字節(jié)碼具有平臺(tái)無(wú)關(guān)性;代碼長(zhǎng)度相比C/C++/Java短很多;這些特性導(dǎo)致Python的開(kāi)發(fā)周期短,而且可以作為快速原型開(kāi)發(fā)的語(yǔ)言使用,即先用Python實(shí)現(xiàn)程序的主要模塊,并測(cè)試發(fā)現(xiàn)bug,等模塊穩(wěn)定了之后再用C/C++等語(yǔ)言來(lái)實(shí)現(xiàn)替換Python模塊;Python受到開(kāi)源社區(qū)的廣泛歡迎,大批的志愿者為Python語(yǔ)言貢獻(xiàn)了源代碼,使得Python的功能日趨完善。
Python還有很多不完善的地方,Python社區(qū)非?;钴S,程序員可以通過(guò)提交PEP(Python增強(qiáng)提議)提出對(duì)Python語(yǔ)言改進(jìn)的方案,促使Python語(yǔ)言不斷發(fā)展;Python已經(jīng)有15年的歷史了,這期間不斷的有新的語(yǔ)言特征被加進(jìn)來(lái),2.2版本之后的Python更傾向?qū)Υ笮蛙浖闹С郑热珈o態(tài)方法,generator,property,method decorator等特征,對(duì)其它語(yǔ)言的優(yōu)點(diǎn)Python也很注意學(xué)習(xí)。
參考資料
[1] Python Documentation (Release
[2] Alex Martelli, David Ascher 《Python Cookbook》 O’Reilly
[3] Mark Lutz, David Ascher 《Leaning Python》 O’Reilly
[4] http://www.python.org Python主頁(yè)
[5] http://www.pythonology.com Python成功案例
[6] John K. Ousterhout “Scripting: Higher Level Programming for the 21st Century” IEEE Computer magazine March, 1998
一篇比較老的論文,講腳本語(yǔ)言跟系統(tǒng)編程語(yǔ)言的對(duì)比并預(yù)測(cè)前者的未來(lái)
聯(lián)系客服