Python語言介紹html
說到Python語言,就不得不說一下它的創始人Guido van Rossum(1956 -- ?), 他在開發PYTHON語言以前曾使用過幾年的ABC語言,ABC是一門主要用於教學目的語言(教計算機系的學生如何設計一門開發語言),Guido 在開發PYTHON時借鑑了不少ABC語言的特性,因此後來人們包括Guido本身也認爲,PYTHON語言的前身就是ABC語言。關於創做PYTHON語言的初衷,Guido在1996年寫到:java
Over six years ago, in December 1989, I was looking for a "hobby" programming project that would keep me occupied during the week around Christmas. My office ... would be closed, but I had a home computer, and not much else on my hands. I decided to write an interpreter for the new scripting language I had been thinking about lately: a descendant of ABC that would appeal to Unix/C hackers. I chose Python as a working title for the project, being in a slightly irreverent mood (and a big fan of Monty Python's Flying Circus).python
在六年前的1989.12月份,我爲了在聖誕假期打發無聊時間找點事幹(估計是寫代碼找不到對象),決定爲我最近一直在構思的一門新的腳本語言寫個解釋器,這門語言的前身ABC(就Guido本人看來,ABC這種語言很是優美和強大,是專門爲專業的程序設計師使用的。可是ABC語言並無成功,究其緣由,吉多認爲是非開放形成的。吉多決心在Python中避免這一錯誤,並取得了很是好的效果,完美結合了C和其餘一些語言)語言更可能是被UNIX/C黑客使用,我選擇PYTHONP這個名字作爲這個開發項目的名字,起這個名字的一個緣由是由於我是Month Python’s Flying Circus(英國的一個電視喜劇)的超級粉絲。c++
就這樣,python在Guido手中誕生了,它的第一個版本實現是在MAC電腦上,一直在90年代,PYTHON的開放性、語法的簡潔性大受不少程序員的喜歡,不少人拿它來快速的開發一些腳本和工具,並不斷的向官方提交新的代碼和第三方模塊,所以PYTHON能作的事情也愈發多了起來,一些大公司像YAHOO、EBAY也開始在生產環境中使用PYTHON。到了2000年10月16號,PYTHON2.0發佈了,相比以前的1.x版本,實現了完整的垃圾回收,而且支持UNICODE,同時整個開發過程更加透明,社區對PYTHON的開發進度的影響逐漸增大。從2000年第一個2.0版本發佈到寫本書的2015止,2.X版本最主流使用的工業版本,雖然PYTHON官方於2008年就發佈了Python3.0,但因爲此版本並不徹底兼容以前的普遍使用的2.4版本,這致使不少基於2.4開發軟件跟本沒法在3.0的平臺 上運行,所以3.0的推廣也很是緩慢,爲解決這個問題,python官方很快又推出兼容2.4和3.0兩個版本的2.6,這個版本兼容了原來的2.4版本,又支持了不少3.0的特性,而且官方還開發了專門的幫助將2.x轉爲3.0版本的轉換工具,所以,python3.0的使用纔開始逐漸多了起來,不過,如今主流的工業版本依然是2.6和2.7過渡版本,所以本書主要仍是圍繞着2.7的版原本學習,不過同窗們不用擔憂,由於2.7支持了很是多3.x版本的特性,等到幾年後3.0版本普遍使用時,你由2.x轉向3.x會像由 windows xp轉向使用win 7同樣簡單。程序員
再說回Guido, 這哥們如今還掌控着python的發展方向,他於2005年加入谷歌工做,所以也推進了python在谷歌內部實現了普遍使用,2012年,他加入世界上最大的雲存儲公司Dropbox,該公司產品幾乎所有基於python開發,全世界的用戶天天在上面分享和上傳超過10億個文件。web
Python 是一門什麼樣的語言?算法
編程語言主要從如下幾個角度爲進行分類,編譯型和解釋型、靜態語言和動態語言、強類型定義語言和弱類型定義語言,每一個分類表明什麼意思呢,咱們一塊兒來看一下。shell
編譯型和解釋型
咱們先看看編譯型,其實它和彙編語言是同樣的:也是有一個負責翻譯的程序來對咱們的源代碼進行轉換,生成相對應的可執行代碼。這個過程說得專業一點,就稱爲編譯(Compile),而負責編譯的程序天然就稱爲編譯器(Compiler)。若是咱們寫的程序代碼都包含在一個源文件中,那麼一般編譯以後就會直接生成一個可執行文件,咱們就能夠直接運行了。但對於一個比較複雜的項目,爲了方便管理,咱們一般把代碼分散在各個源文件中,做爲不一樣的模塊來組織。這時編譯各個文件時就會生成目標文件(Object file)而不是前面說的可執行文件。通常一個源文件的編譯都會對應一個目標文件。這些目標文件裏的內容基本上已是可執行代碼了,但因爲只是整個項目的一部分,因此咱們還不能直接運行。待全部的源文件的編譯都大功告成,咱們就能夠最後把這些半成品的目標文件「打包」成一個可執行文件了,這個工做由另外一個程序負責完成,因爲此過程好像是把包含可執行代碼的目標文件鏈接裝配起來,因此又稱爲連接(Link),而負責連接的程序就叫……就叫連接程序(Linker)。連接程序除了連接目標文件外,可能還有各類資源,像圖標文件啊、聲音文件啊什麼的,還要負責去除目標文件之間的冗餘重複代碼,等等,因此……也是挺累的。連接完成以後,通常就能夠獲得咱們想要的可執行文件了。
上面咱們大概地介紹了編譯型語言的特色,如今再看看解釋型。噢,從字面上看,「編譯」和「解釋」的確都有「翻譯」的意思,它們的區別則在於翻譯的時機安排不大同樣。打個比方:假如你打算閱讀一本外文書,而你不知道這門外語,那麼你能夠找一名翻譯,給他足夠的時間讓他從頭至尾把整本書翻譯好,而後把書的母語版交給你閱讀;或者,你也馬上讓這名翻譯輔助你閱讀,讓他一句一句給你翻譯,若是你想往回看某個章節,他也得從新給你翻譯。
兩種方式,前者就至關於咱們剛纔所說的編譯型:一次把全部的代碼轉換成機器語言,而後寫成可執行文件;然後者就至關於咱們要說的解釋型:在程序運行的前一刻,還只有源程序而沒有可執行程序;而程序每執行到源程序的某一條指令,則會有一個稱之爲解釋程序的外殼程序將源代碼轉換成二進制代碼以供執行,總言之,就是不斷地解釋、執行、解釋、執行……因此,解釋型程序是離不開解釋程序的。像早期的BASIC就是一門經典的解釋型語言,要執行BASIC程序,就得進入BASIC環境,而後才能加載程序源文件、運行。解釋型程序中,因爲程序老是以源代碼的形式出現,所以只要有相應的解釋器,移植幾乎不成問題。編譯型程序雖然源代碼也能夠移植,但前提是必須針對不一樣的系統分別進行編譯,對於複雜的工程來講,的確是一件不小的時間消耗,何況極可能一些細節的地方仍是要修改源代碼。並且,解釋型程序省卻了編譯的步驟,修改調試也很是方便,編輯完畢以後便可當即運行,沒必要像編譯型程序同樣每次進行小小改動都要耐心等待漫長的Compiling…Linking…這樣的編譯連接過程。不過凡事有利有弊,因爲解釋型程序是將編譯的過程放到執行過程當中,這就決定了解釋型程序註定要比編譯型慢上一大截,像幾百倍的速度差距也是不足爲奇的。
編譯型與解釋型,二者各有利弊。前者因爲程序執行速度快,同等條件下對系統要求較低,所以像開發操做系統、大型應用程序、數據庫系統等時都採用它,像C/C++、Pascal/Object Pascal(Delphi)、VB等基本均可視爲編譯語言,而一些網頁腳本、服務器腳本及輔助開發接口這樣的對速度要求不高、對不一樣系統平臺間的兼容性有必定要求的程序則一般使用解釋性語言,如Java、JavaScript、VBScript、Perl、Python等等。
但既然編譯型與解釋型各有優缺點又相互對立,因此一批新興的語言都有把二者折衷起來的趨勢,例如Java語言雖然比較接近解釋型語言的特徵,但在執行以前已經預先進行一次預編譯,生成的代碼是介於機器碼和Java源代碼之間的中介代碼,運行的時候則由JVM(Java的虛擬機平臺,可視爲解釋器)解釋執行。它既保留了源代碼的高抽象、可移植的特色,又已經完成了對源代碼的大部分預編譯工做,因此執行起來比「純解釋型」程序要快許多。而像VB6(或者之前版本)、C#這樣的語言,雖然表面上看生成的是.exe可執行程序文件,但VB6編譯以後實際生成的也是一種中介碼,只不過編譯器在前面安插了一段自動調用某個外部解釋器的代碼(該解釋程序獨立於用戶編寫的程序,存放於系統的某個DLL文件中,全部以VB6編譯生成的可執行程序都要用到它),以解釋執行實際的程序體。C#(以及其它.net的語言編譯器)則是生成.net目標代碼,實際執行時則由.net解釋系統(就像JVM同樣,也是一個虛擬機平臺)進行執行。固然.net目標代碼已經至關「低級」,比較接近機器語言了,因此仍將其視爲編譯語言,並且其可移植程度也沒有Java號稱的這麼強大,Java號稱是「一次編譯,處處執行」,而.net則是「一次編碼,處處編譯」。呵呵,固然這些都是題外話了。總之,隨着設計技術與硬件的不斷髮展,編譯型與解釋型兩種方式的界限正在不斷變得模糊。數據庫
動態語言和靜態語言
一般咱們所說的動態語言、靜態語言是指動態類型語言和靜態類型語言。編程
(1)動態類型語言:動態類型語言是指在運行期間纔去作數據類型檢查的語言,也就是說,在用動態類型的語言編程時,永遠也不用給任何變量指定數據類型,該語言會在你第一次賦值給變量時,在內部將數據類型記錄下來。Python和Ruby就是一種典型的動態類型語言,其餘的各類腳本語言如VBScript也多少屬於動態類型語言。
(2)靜態類型語言:靜態類型語言與動態類型語言恰好相反,它的數據類型是在編譯其間檢查的,也就是說在寫程序時要聲明全部變量的數據類型,C/C++是靜態類型語言的典型表明,其餘的靜態類型語言還有C#、JAVA等。
對於動態語言與靜態語言的區分,套用一句流行的話就是:Static typing when possible, dynamic typing when needed。
強類型定義語言和弱類型定義語言
(1)強類型定義語言:強制數據類型定義的語言。也就是說,一旦一個變量被指定了某個數據類型,若是不通過強制轉換,那麼它就永遠是這個數據類型了。舉個例子:若是你定義了一個整型變量a,那麼程序根本不可能將a看成字符串類型處理。強類型定義語言是類型安全的語言。
(2)弱類型定義語言:數據類型能夠被忽略的語言。它與強類型定義語言相反, 一個變量能夠賦不一樣數據類型的值。
強類型定義語言在速度上可能略遜色於弱類型定義語言,可是強類型定義語言帶來的嚴謹性可以有效的避免許多錯誤。另外,「這門語言是否是動態語言」與「這門語言是否類型安全」之間是徹底沒有聯繫的!
例如:Python是動態語言,是強類型定義語言(類型安全的語言); VBScript是動態語言,是弱類型定義語言(類型不安全的語言); JAVA是靜態語言,是強類型定義語言(類型安全的語言)。
經過上面這些介紹,咱們能夠得出,python是一門動態解釋性的強類型定義語言。那這些基因使成就了Python的哪些優缺點呢?咱們繼續往下看。
Python能作什麼?
Python是一門綜合性的語言,你幾乎能在計算機上經過Python作任何事情,如下是Python應該最普遍的幾個方面:
Python的優缺點
先看優勢
再看缺點:
固然,Python還有一些其它的小缺點,在這就不一一列舉了,我想說的是,任何一門語言都不是完美的,都有擅長和不擅長作的事情,建議各位不要拿一個語言的劣勢去跟另外一個語言的優點來去比較,語言只是一個工具,是實現程序設計師思想的工具,就像咱們以前中學學幾什麼時候,有的時候須要要圓規,有的時候須要用三角尺同樣,拿相應的工具去作它最擅長的事纔是正確的選擇。以前不少人問我Shell和Python到底哪一個好?我回答說Shell是個腳本語言,但Python不僅是個腳本語言,能作的事情更多,而後又有鑽牛角尖的人說徹底不必學Python, Python能作的事情Shell均可以作,只要你足夠牛B,而後又舉了用Shell能夠寫俄羅斯方塊這樣的遊戲,對此我能說表達只能是,不要跟SB理論,SB會把你拉到跟他同樣的高度,而後用充分的經驗把你打倒。
Python安裝
我以爲這一節是最沒什麼好講的了,Python如今已經默認安裝在了全部的*nix發行版本上,對於Windows平臺,也只須要到Python官網(http://www.python.org)直接下載Windows版本就能夠了,但對於版本的選擇,可能好多新手會有點困惑,不知道選擇2.x or 3.x好,若是你如今還有這個困惑的話,表明你沒好好看上面的簡介,請回去本身複習,我這裏的建議是下載最新的2.x版本使用便可,
除了官方提供的標準Python版本,還有一些其它的用於特定方向的發行版本,好比PyQt主要是用來作GUI圖形界面的,能夠用來代替Python的Tkinter,其它替代者還有wxPython、PyGTK等,還有PortablePython,是一個免安裝的Windows 發行版本,若是你想在不安裝任何python環境的狀況下就在windows上運行python程序,只須要把PortablePython 拷貝到你的Windows機器上便可。
Python解釋器
當咱們編寫Python代碼時,咱們獲得的是一個包含Python代碼的以.py
爲擴展名的文本文件。要運行代碼,就須要Python解釋器去執行.py
文件。
因爲整個Python語言從規範到解釋器都是開源的,因此理論上,只要水平夠高,任何人均可以編寫Python解釋器來執行Python代碼(固然難度很大)。事實上,確實存在多種Python解釋器。
當咱們從Python官方網站下載並安裝好Python 2.7後,咱們就直接得到了一個官方版本的解釋器:CPython。這個解釋器是用C語言開發的,因此叫CPython。在命令行下運行python
就是啓動CPython解釋器。
CPython是使用最廣的Python解釋器。教程的全部代碼也都在CPython下執行。
IPython是基於CPython之上的一個交互式解釋器,也就是說,IPython只是在交互方式上有所加強,可是執行Python代碼的功能和CPython是徹底同樣的。比如不少國產瀏覽器雖然外觀不一樣,但內核其實都是調用了IE。
CPython用>>>
做爲提示符,而IPython用In [
序號
]:
做爲提示符。
PyPy是另外一個Python解釋器,它的目標是執行速度。PyPy採用JIT技術,對Python代碼進行動態編譯(注意不是解釋),因此能夠顯著提升Python代碼的執行速度。
絕大部分Python代碼均可以在PyPy下運行,可是PyPy和CPython有一些是不一樣的,這就致使相同的Python代碼在兩種解釋器下執行可能會有不一樣的結果。若是你的代碼要放到PyPy下執行,就須要瞭解PyPy和CPython的不一樣點。
Jython是運行在Java平臺上的Python解釋器,能夠直接把Python代碼編譯成Java字節碼執行。
IronPython和Jython相似,只不過IronPython是運行在微軟.Net平臺上的Python解釋器,能夠直接把Python代碼編譯成.Net的字節碼。
Python的解釋器不少,但使用最普遍的仍是CPython。若是要和Java或.Net平臺交互,最好的辦法不是用Jython或IronPython,而是經過網絡調用來交互,確保各程序之間的獨立性。
本教程的全部代碼只確保在CPython 2.7版本下運行。請務必在本地安裝CPython(也就是從Python官方網站下載的安裝程序)。
第一個Python程序
好了,前面說了這麼多,是時候該進入正題啦,下面我就來寫一下第一個Python程序 !
首先找一個版本比較新的Linux系統, 執行Python –V 查看一下你的Python版本,請確保你的Python版本在2.6如下,若是你還能發現2.4的版本的話,那隻能說你的系統實在太老了,快換了丫的。
$ python -V
Python 2.7.5
接下來,建立一個文件名爲,myFirstPyProgram.py
vi myFirstPyProgram.py
#!/usr/bin/env python
print 「Hello,World!」
print 「Goodbye,World!」
保存後執行:
$ python myFirstPyProgram.py
Hello,World!
Goodbye, World!
哈哈,第一個程序就這樣寫完了,讓咱們一塊兒來看看它每句話的意思:
因此,若是肯定你的程序會變成可執行文件被調用的話,那麼務必要加上解釋器聲明
3.用print 語法將後面的字符串打印到屏幕上,和shell腳本的echo、java和c的printf是一個意思噢。
寫個猜年齡的小程序
剛纔咱們寫了學習任何一門語言都要先寫的儀式感很強的HelloWorld程序,感受是否是有點太簡單了?哈,那咱們作一個稍微深刻點的,需求以下:
咱們在程序中先給一我的定義好年齡,而後讓用戶去猜想,用戶輸入他猜想的數字後,咱們再來判斷他猜想的是否正確。
好的,我先來直接上代碼:
if (var1 == var2 ){
console.log(‘yes,var1 equals to var2’);
}else{
alert(‘no ,they are not equal.’);
}
看到上面的那麼多大括號了麼,沒錯,就是經過大括號來肯定做用域的,因此他們不強制縮進。
Python的變量及數據類型
上面猜想用戶年齡的程序中已經涉及到了變量、數據類型的概念,有些小夥伴可能還暈圈呢,咱們下面再來詳細介紹下
數據類型
一個程序要運行,就要先描述其算法。描述一個算法應先說明算法中要用的數據,數據以變量或常量的形式來描述。每一個變量或常量都有數據類型。Python的基本數據類型有5種: 整型(int), 浮點型(float), 字符型(string), 布爾型(bool),空值(None).
整數
Python可處理任意大小的整數,在程序中的表示方法和數學上的寫法徹底同樣。
浮點數
浮點數也就是小數,之因此稱爲浮點數,是由於按照科學記數法表示時,一個浮點數的小數點位置是可變的,好比,1.23x109和12.3x108是相等的。浮點數能夠用數學寫法,如1.23
,3.14
,-9.01
,等等。可是對於很大或很小的浮點數,就必須用科學計數法表示,把10用e替代,1.23x109就是1.23e9
,或者12.3e8
,0.000012能夠寫成1.2e-5
,等等。
整數和浮點數在計算機內部存儲的方式是不一樣的,整數運算永遠是精確的(除法難道也是精確的?是的!),而浮點數運算則可能會有四捨五入的偏差。
字符串是以''或""括起來的任意文本,好比'abc'
,"xyz"
等等。請注意,''或""自己只是一種表示方式,不是字符串的一部分,所以,字符串'abc'
只有a
,b
,c
這3個字符。若是'
自己也是一個字符,那就能夠用""括起來,好比"I'm OK"
包含的字符是I
,'
,m
,空格,O
,K
這6個字符。
若是字符串內部既包含'
又包含"
怎麼辦?能夠用轉義字符\
來標識,好比:
'I\'m \"OK\"!'
表示的字符串內容是:
I'm "OK"!
轉義字符\
能夠轉義不少字符,好比\n
表示換行,\t
表示製表符,字符\
自己也要轉義,因此\\
表示的字符就是\
,能夠在Python的交互式命令行用print打印字符串看看:
>>> print 'I\'m ok.' I'm ok. >>> print 'I\'m learning\nPython.' I'm learning Python. >>> print '\\\n\\' \ \
若是字符串裏面有不少字符都須要轉義,就須要加不少\
,爲了簡化,Python還容許用r''
表示''
內部的字符串默認不轉義,能夠本身試試:
>>> print '\\\t\\' \ \ >>> print r'\\\t\\' \\\t\\
若是字符串內部有不少換行,用\n
寫在一行裏很差閱讀,爲了簡化,Python容許用'''...'''
的格式表示多行內容,能夠本身試試:
>>> print '''line1 ... line2 ... line3''' line1 line2 line3
上面是在交互式命令行內輸入,若是寫成程序,就是:
print '''line1 line2 line3'''
多行字符串'''...'''
還能夠在前面加上r
使用,請自行測試。
布爾值和布爾代數的表示徹底一致,一個布爾值只有True
、False
兩種值,要麼是True
,要麼是False
,在Python中,能夠直接用True
、False
表示布爾值(請注意大小寫),也能夠經過布爾運算計算出來:
>>> True True >>> False False >>> 3 > 2 True >>> 3 > 5 False
布爾值能夠用and
、or
和not
運算。
and
運算是與運算,只有全部都爲True
,and
運算結果纔是True
:
>>> True and True True >>> True and False False >>> False and False False
or
運算是或運算,只要其中有一個爲True
,or
運算結果就是True
:
>>> True or True True >>> True or False True >>> False or False False
not
運算是非運算,它是一個單目運算符,把True
變成False
,False
變成True
:
>>> not True False >>> not False True
布爾值常常用在條件判斷中,好比:
if age >= 18: print 'adult' else: print 'teenager'
空值是Python裏一個特殊的值,用None
表示。None
不能理解爲0
,由於0
是有意義的,而None
是一個特殊的空值。
此外,Python還提供了列表、字典等多種數據類型,還容許建立自定義數據類型,咱們後面會繼續講到。<引用2>
變量和常量
在計算機中,變量就是用來在程序運行期間存儲各類須要臨時保存能夠不斷改變的數據的標識符,一個變量應該有一個名字,而且在內存中佔據必定的存儲單元,在該存儲單元中存放變量的值。請注意區分變量名和變量值這兩個不一樣的概念,看下圖:
變量命名規則
先介紹標識符的概念。和其餘高級語言同樣,用來標識變量、符號常量、函數、數組、類型等實體名字的有效字符序列稱爲標識符(identifier)。簡單地說,標識符就是一個名字。變量名是標識符的一種,變量的名字必須遵循標識符的命名規則。
Python語言和java,c++等不少語言同樣,規定標識符只能由字母、數字和下劃線3種字符組成,且第一個字符必須爲字母或下劃線。下面列出的是合法的標識符,也是合法的變量名:
sum, average, total, day, month, Student_name, tan, BASIC, li_ling
下面是不合法的標識符和變量名:
M.D.John, $442, #4, 3G64, Alex Li, C++, Zhang-ling,姓名, U.S.A.
注意:在Python中,大寫字母和小寫字母被認爲是兩個不一樣的字符。所以,sum和SUM是兩個不一樣的變量名。通常地,變量名用小寫字母表示,與人們平常習慣一致,以增長可讀性。應注意變量名不能與Python的關鍵字、系統函數名和類名相同。
變量名命名習慣
當你的代碼越寫越多的時候,你會發現你定義的變量也會愈來愈多,爲了增長代碼的易讀性和方便調試,給變量起名時必定要遵循必定的命名習慣,你起的變量名稱最好能讓人一眼就大概知道這個變量是幹什麼用的,好比,getUserName一看就知道,這個變量應該是要獲取用戶的姓名,check_current_conn_count表明是要檢查如今的鏈接數,只有這樣,別人才能在看你的代碼時知道你的這些變量的做用,而若是你把變量名全起成了var1,var2,var3…..varN,那別人再看你的代碼時會罵死你的。
變量名的定義在能表達清楚它的做用的前提下最越簡潔越好,能用一個單詞表述清楚的儘可能就不要用兩個。變量起名時通常有這麼幾種寫法,你以爲哪一種最簡潔,你就選哪一種吧。
CheckCurrentConnCount
check_current_conn_count
checkCurrentConnCount
很差的起名:
CHECKCURRENTCONNCOUNT
Var1 var2 var3 varN
Checkcurrentconncount
定義變量
瞭解了變量的概念和用途後,咱們一塊兒來定義幾個簡單的變量看一下
name = ‘Alex Li’ #name 是字符串,字符串要加上引號噢
age = 29 #age 是整數,整數不要加引號,加了引號後就變成字符串了
has_girlfriend = False #是布爾值,通常用這個作邏輯判斷,如if has_girlfriend:print ‘good for you !’
age = age + 1 #這個結果應該是30,運算流程是先將=號後面的age +1結果算出,而後再把這個結果重賦值給age, 因爲age以前的值是29,從新賦值後,age值變爲30.
最後,理解變量在計算機內存中的表示也很是重要。當咱們寫:
name = 'Alex'
時,Python解釋器幹了兩件事情:
也能夠變量name賦值給另外一個變量name2,這個操做其實是把變量name2指向的數據,例如:
唉?不是已經把name2 等於name變量了嗎?name 值改了之後,name2不跟着改嗎?沒錯,當name 的值由」Alex」改爲」Jack」後,name2仍是指向原來的」Alex」,咱們來一步步分析一下:
1. 定義name=」Alex」,解釋器建立了字符串」Alex」和變量name,並把name指向了」Alex」
2. 執行name2=name,解釋器建立了name2變量,並把name2指向了name變量所指向的字符串
3. 這時經過id內置函數來查看一下這兩個變量分別指向的內存地址,結果都是指向了同一地址。
4. 執行name=」Jack」,解釋器建立一個新的變量」Jack」,並把name的指向改爲了」Jack」
5. 此時再查看兩個變量的內存地址指向就會發現,name的指向已經變成了一個新的地址,也就是」Jack」所在內存地址,可是name2依然仍是指向原來的」Alex」。
Now, 你明白了嗎? 再總結一下,當你把一個變量name賦值給另外一個變量name2時,解釋器只是把name變量所指向的內存地址賦值給了name2,所以name 和 name2並未發生直接的關聯,只不過是他們都同時指向了同一個內存地址而已,這也就是爲何你把name再指向一個新地址後,而name2的值還保持不變的緣由。
常量
剛纔說到了變量,還有一律念就是常量,所謂常量就是不能變的變量,好比經常使用的數學常數π就是一個常量。在Python中,一般用所有大寫的變量名錶示常量:
PI = 3.14159265359
但事實上PI仍然是一個變量,Python根本沒有任何機制保證PI不會被改變,因此,用所有大寫的變量名錶示常量只是一個習慣上的用法,若是你必定要改變變量PI的值,也沒人能攔住你。
數據運算符
和其它語言同樣,python也支持進行各類各樣的數學和邏輯運算,咱們一塊兒來看一些。
python語言支持如下幾種運算
算術運算
比較運算
Assignment Operators
二進制運算
關係運算
驗證運算
算術運算
如下例子a = 10 , b= 20
運算符 |
描述 |
示例 |
+ |
加法運算 |
a + b 得 30 |
- |
減法運算 |
a - b 得 -10 |
* |
乘法運算 |
a * b 得 200 |
/ |
除法運算 |
b / a 得 2 |
% |
取模 - 將%號左邊的值除以%號右邊的值而且將獲得的結果的餘數返回 |
10%5得0 ,10%3 得1, 20%7 得6 |
** |
冪 - 返回x的y次冪,就是返回多少次方 |
2**8 得256 |
// |
取整除 - 返回x除以y的商的整數部分 |
9//2得4 , 9.0//2.0得4.0 |
比較運算
如下例子a = 10 , b= 20
運算符 |
描述 |
示例 |
== |
判斷兩個對象是否相等 |
(a == b) is not true. |
!= |
判斷兩個對象是否不相等 |
(a != b) is true. |
<> |
判斷兩個對象是否不相等 |
(a <> b) is true. 與 != 運算符同樣. |
> |
大於 - 返回a是否大於b |
(a > b) is not true. |
< |
小於 - 返回a是否小於b |
(a < b) is true. |
>= |
大於等於 - 返回a 是否大於等於b |
(a >= b) is not true. |
<= |
小於等於 - 返回a 是否小於等於b |
(a <= b) is true. |
賦值運算
運算符 |
描述 |
示例 |
= |
賦值 - 將右邊的值賦值給左邊的變量名 |
c = a + b 將會把a+b的結果賦值給c |
+= |
自加賦值 - 將+=號左邊的值與+=號右邊的值相加,而後再把結果賦值給+=號左右的值 |
c += a至關於 c = c + a |
-= |
自減賦值 |
c -= a至關於 c = c - a |
*= |
自乘賦值 |
c *= a 至關於 c = c * a |
/= |
自除賦值 |
c /= a 至關於 c = c / a |
%= |
自取模賦值 |
c %= a 至關於 c = c % a |
**= |
自求冪賦值 |
c **= a 至關於 c = c ** a |
//= |
自取整賦值 |
c //= a 至關於 c = c // a |
按位運算(二進制運算)
咱們都知道,計算機處理數據的時候都會把數據最終變成0和1的二進制來進行運算,也就是說,計算機其實只認識0和1, 那按位運算其實就是把數字轉換成二進制的形式後再進行位運算的,唉呀,說的好迷糊,直接看例子,咱們設定a=60; b=13; 要進行位運算,就得把他們先轉成2進制格式,那0和1是如何表示60和13的呢?學過計算機基礎的人都知道,計算機最小的存儲單位是字節,也就是說一個數字、一個字母最少須要用一個字節來存儲,而後呢,一個字節又由8個2進制位來表示,也就是8bit,因此呢,一個計算機中最小的數據也須要用一個字節來存儲噢。那爲是什麼8位而不是9位、10位、20位呢?這個問題上學的時候應該都講過,不明白的本身網上查下吧再。8個二進制如何表示60這個數字呢?聰明的計算機先人們想到了用佔位的方式來輕鬆的實現了,怎麼佔位呢?以下表所示,咱們把8個二進制位依次排列,每一個二進制位表明一個固定的數字,這個數字是由2的8次方得來的,即每一個二進制位表明的值就是2的第幾回方的值,8個二進制位能表示的最大數是2**8=256, 那把60分解成二進制其實就是以此在這8位上作個比對,只要把其中的幾位相加,若是結果正好等於60,那這個位就找對了,首先看60 確定佔不了128和64那兩位,不佔位就設爲0,後面的32+16+8+4=60,因此這幾位要設置爲1,其它的全設置爲0,13的二進制算法也是同樣的。
二進制位數 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
每位所表明的數字 |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
60 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
13 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
好,知道了10進制如何轉2進制了以後,咱們接着來看,若是進行2個10進制數字的位運算
運算符 |
描述 |
示例 |
& |
與運算,這個二進制位必須在2組數中都爲真,結果才返回真 |
(a & b)得12,二進制位: 0000 1100 |
| |
或運算,這個二進制位只需在其中一組數據中爲真即返回真 |
(a | b)得 61,二進制位: 0011 1101 |
^ |
異或運算,只要這個二進制位在兩組數據中不相同就返回真 |
(a ^ b)得 49 ,二進制位: 0011 0001 |
<< |
左移運算,將a總體向左移2位 |
a << 2得240,二進制位: 1111 0000 |
>> |
右移運算,將a總體向左移3位 |
a >> 3得 7 ,二進制位: 0000 0111 |
看下面的運算過程:
二進制位 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
結果 |
每位所表明的數字 |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
|
60 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
|
13 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
|
&與運算 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
12 |
|或運算 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
61 |
^異或運算 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
49 |
a<<2 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
240 |
a>>3 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
7 |
後面還有
邏輯運算符 and 、or 、not
關係運算符 in 、not in
驗證運算符 is 、 is not
由於咱們如今尚未學流程控制相關的,如今說這些反而會讓你迷惑,先忘掉這幾個吧,之後咱們用到的時候你天然就會明白了哈。
咱們已經講過了,字符串也是一種數據類型,可是,字符串比較特殊的是還有一個編碼問題。
由於計算機只能處理數字,若是要處理文本,就必須先把文本轉換爲數字才能處理。最先的計算機在設計時採用8個比特(bit)做爲一個字節(byte),因此,一個字節能表示的最大的整數就是255(二進制11111111=十進制255),若是要表示更大的整數,就必須用更多的字節。好比兩個字節能夠表示的最大整數是65535
,4個字節能夠表示的最大整數是4294967295
。
因爲計算機是美國人發明的,所以,最先只有127個字母被編碼到計算機裏,也就是大小寫英文字母、數字和一些符號,這個編碼表被稱爲ASCII
編碼,好比大寫字母A
的編碼是65
,小寫字母z
的編碼是122
。
可是要處理中文顯然一個字節是不夠的,至少須要兩個字節,並且還不能和ASCII編碼衝突,因此,中國製定了GB2312
編碼,用來把中文編進去。
你能夠想獲得的是,全世界有上百種語言,日本把日文編到Shift_JIS
裏,韓國把韓文編到Euc-kr
裏,各國有各國的標準,就會不可避免地出現衝突,結果就是,在多語言混合的文本中,顯示出來會有亂碼。
所以,Unicode應運而生。Unicode把全部語言都統一到一套編碼裏,這樣就不會再有亂碼問題了。
Unicode標準也在不斷髮展,但最經常使用的是用兩個字節表示一個字符(若是要用到很是偏僻的字符,就須要4個字節)。現代操做系統和大多數編程語言都直接支持Unicode。
如今,捋一捋ASCII編碼和Unicode編碼的區別:ASCII編碼是1個字節,而Unicode編碼一般是2個字節。
字母A
用ASCII編碼是十進制的65
,二進制的01000001
;
字符0
用ASCII編碼是十進制的48
,二進制的00110000
,注意字符'0'
和整數0
是不一樣的;
漢字中
已經超出了ASCII編碼的範圍,用Unicode編碼是十進制的20013
,二進制的01001110 00101101
。
你能夠猜想,若是把ASCII編碼的A
用Unicode編碼,只須要在前面補0就能夠,所以,A
的Unicode編碼是00000000 01000001
。
新的問題又出現了:若是統一成Unicode編碼,亂碼問題今後消失了。可是,若是你寫的文本基本上所有是英文的話,用Unicode編碼比ASCII編碼須要多一倍的存儲空間,在存儲和傳輸上就十分不划算。
因此,本着節約的精神,又出現了把Unicode編碼轉化爲「可變長編碼」的UTF-8
編碼。UTF-8編碼把一個Unicode字符根據不一樣的數字大小編碼成1-6個字節,經常使用的英文字母被編碼成1個字節,漢字一般是3個字節,只有很生僻的字符纔會被編碼成4-6個字節。若是你要傳輸的文本包含大量英文字符,用UTF-8編碼就能節省空間:
字符 |
ASCII |
Unicode |
UTF-8 |
A |
01000001 |
00000000 01000001 |
01000001 |
中 |
x |
01001110 00101101 |
11100100 10111000 10101101 |
從上面的表格還能夠發現,UTF-8編碼有一個額外的好處,就是ASCII編碼實際上能夠被當作是UTF-8編碼的一部分,因此,大量只支持ASCII編碼的歷史遺留軟件能夠在UTF-8編碼下繼續工做。
搞清楚了ASCII、Unicode和UTF-8的關係,咱們就能夠總結一下如今計算機系統通用的字符編碼工做方式:
在計算機內存中,統一使用Unicode編碼,當須要保存到硬盤或者須要傳輸的時候,就轉換爲UTF-8編碼。
用記事本編輯的時候,從文件讀取的UTF-8字符被轉換爲Unicode字符到內存裏,編輯完成後,保存的時候再把Unicode轉換爲UTF-8保存到文件:
瀏覽網頁的時候,服務器會把動態生成的Unicode內容轉換爲UTF-8再傳輸到瀏覽器:
因此你看到不少網頁的源碼上會有相似<meta charset="UTF-8" />
的信息,表示該網頁正是用的UTF-8編碼。
搞清楚了使人頭疼的字符編碼問題後,咱們再來研究Python對Unicode的支持。
由於Python的誕生比Unicode標準發佈的時間還要早,因此最先的Python只支持ASCII編碼,普通的字符串'ABC'
在Python內部都是ASCII編碼的。Python提供了ord()和chr()函數,能夠把字母和對應的數字相互轉換:
>>> ord('A') 65 >>> chr(65) 'A'
Python在後來添加了對Unicode的支持,以Unicode表示的字符串用u'...'
表示,好比:
>>> print u'中文'中文>>> u'中' u'\u4e2d'
寫u'
中
'
和u'\u4e2d'
是同樣的,\u
後面是十六進制的Unicode碼。所以,u'A'
和u'\u0041'
也是同樣的。
兩種字符串如何相互轉換?字符串'xxx'
雖然是ASCII編碼,但也能夠當作是UTF-8編碼,而u'xxx'
則只能是Unicode編碼。
把u'xxx'
轉換爲UTF-8編碼的'xxx'
用encode('utf-8')
方法:
>>> u'ABC'.encode('utf-8') 'ABC' >>> u'中文'.encode('utf-8') '\xe4\xb8\xad\xe6\x96\x87'
英文字符轉換後表示的UTF-8的值和Unicode值相等(但佔用的存儲空間不一樣),而中文字符轉換後1個Unicode字符將變爲3個UTF-8字符,你看到的\xe4
就是其中一個字節,由於它的值是228
,沒有對應的字母能夠顯示,因此以十六進制顯示字節的數值。len()
函數能夠返回字符串的長度:
>>> len(u'ABC') 3 >>> len('ABC') 3 >>> len(u'中文') 2 >>> len('\xe4\xb8\xad\xe6\x96\x87') 6
反過來,把UTF-8編碼表示的字符串'xxx'
轉換爲Unicode字符串u'xxx'
用decode('utf-8')
方法:
>>> 'abc'.decode('utf-8') u'abc' >>> '\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8') u'\u4e2d\u6587' >>> print '\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')中文
因爲Python源代碼也是一個文本文件,因此,當你的源代碼中包含中文的時候,在保存源代碼時,就須要務必指定保存爲UTF-8編碼。當Python解釋器讀取源代碼時,爲了讓它按UTF-8編碼讀取,咱們一般在文件開頭寫上這兩行:
#!/usr/bin/env python # -*- coding: utf-8 -*-
第一行註釋是爲了告訴Linux/OS X系統,這是一個Python可執行程序,Windows系統會忽略這個註釋;
第二行註釋是爲了告訴Python解釋器,按照UTF-8編碼讀取源代碼,不然,你在源代碼中寫的中文輸出可能會有亂碼。
最後一個常見的問題是如何輸出格式化的字符串。咱們常常會輸出相似'
親愛的
xxx
你好!你
xx
月的話費是
xx
,餘額是
xx'
之類的字符串,而xxx的內容都是根據變量變化的,因此,須要一種簡便的格式化字符串的方式。
在Python中,採用的格式化方式和C語言是一致的,用%
實現,舉例以下:
>>> 'Hello, %s' % 'world' 'Hello, world' >>> 'Hi, %s, you have $%d.' % ('Michael', 1000000) 'Hi, Michael, you have $1000000.'
你可能猜到了,%
運算符就是用來格式化字符串的。在字符串內部,%s
表示用字符串替換,%d
表示用整數替換,有幾個%?
佔位符,後面就跟幾個變量或者值,順序要對應好。若是隻有一個%?
,括號能夠省略。
常見的佔位符有:
%d |
整數 |
%f |
浮點數 |
%s |
字符串 |
%x |
十六進制整數 |
其中,格式化整數和浮點數還能夠指定是否補0和整數與小數的位數:
>>> '%2d-%02d' % (3, 1) ' 3-01' >>> '%.2f' % 3.1415926 '3.14'
若是你不太肯定應該用什麼,%s
永遠起做用,它會把任何數據類型轉換爲字符串:
>>> 'Age: %s. Gender: %s' % (25, True) 'Age: 25. Gender: True'
對於Unicode字符串,用法徹底同樣,但最好確保替換的字符串也是Unicode字符串:
>>> u'Hi, %s' % u'Michael' u'Hi, Michael'
有些時候,字符串裏面的%
是一個普通字符怎麼辦?這個時候就須要轉義,用%%
來表示一個%
:
>>> 'growth rate: %d %%' % 7 'growth rate: 7 %'
因爲歷史遺留問題,Python 2.x版本雖然支持Unicode,但在語法上須要'xxx'
和u'xxx'
兩種字符串表示方式。
Python固然也支持其餘編碼方式,好比把Unicode編碼成GB2312:
>>> u'中文'.encode('gb2312') '\xd6\xd0\xce\xc4'
Try
但這種方式純屬自找麻煩,若是沒有特殊業務要求,請牢記僅使用Unicode和UTF-8這兩種編碼方式。
在Python 3.x版本中,把'xxx'
和u'xxx'
統一成Unicode編碼,即寫不寫前綴u
都是同樣的,而以字節形式表示的字符串則必須加上b
前綴:b'xxx'
。
格式化字符串的時候,能夠用Python的交互式命令行測試,方便快捷。