Python基礎教程資料

 

第一章Python的介紹

一、python介紹

一種面向對象,面向函數的解釋型計算機程序設計語言,由荷蘭人Guido van Rossum於1989年發明,第一個公開發行版發行於1991年。Python是純粹的自由軟件, 源代碼和解釋器CPython遵循 GPL(GNU General Public License)協議[2]. Python語法簡潔清晰,特點之一是強制用空白符(white space)做爲語句縮進。Python具備豐富和強大的庫。它常被暱稱爲膠水語言,可以把用其餘語言製做的各類模塊(尤爲是C/C++)很輕鬆地聯結在一塊兒。常見的一種應用情形是,使用Python快速生成程序的原型(有時甚至是程序的最終界面),而後對其中[3]  有特別要求的部分,用更合適的語言改寫,好比3D遊戲中的圖形渲染模塊,性能要求特別高,就能夠用C/C++重寫,然後封裝爲Python能夠調用的擴展類庫。須要注意的是在您使用擴展類庫時可能須要考慮平臺問題,某些可能不提供跨平臺的實現。java

二、Python的歷史

自從20世紀90年代初Python語言誕生至今,它已被逐漸普遍應用於系統管理任務的處理和Web編程。python

Python的創始人爲Guido van Rossum。1989年聖誕節期間,在阿姆斯特丹,Guido爲了打發聖誕節的無趣,決心開發一個新的腳本解釋程序,作爲ABC 語言的一種繼承。之因此選中Python(大蟒蛇的意思)做爲該編程語言的名字,是由於他是一個叫Monty Python的喜劇團體的愛好者。mysql

 ABC是由Guido參加設計的一種教學語言。就Guido本人看來,ABC 這種語言很是優美和強大,是專門爲非專業程序員設計的。可是ABC語言並無成功,究其緣由,Guido 認爲是其非開放形成的。Guido 決心在Python 中避免這一錯誤。同時,他還想實如今ABC 中閃現過但不曾實現的東西。linux

就這樣,Python在Guido手中誕生了。能夠說,Python是從ABC發展起來,主要受到了Modula-3(另外一種至關優美且強大的語言,爲小型團體所設計的)的影響。而且結合了Unix shell和C的習慣。git

Python[4]  已經成爲最受歡迎的程序設計語言之一。2011年1月,它被TIOBE編程語言排行榜評爲2010年度語言。自從2004年之後,python的使用率呈線性增加[5]  。程序員

因爲Python語言的簡潔性、易讀性以及可擴展性,在國外用Python作科學計算的研究機構日益增多,一些知名大學已經採用Python來教授程序設計課程。例如卡耐基梅隆大學的編程基礎、麻省理工學院的計算機科學及編程導論就使用Python語言講授。衆多開源的科學計算軟件包都提供了Python的調用接口,例如著名的計算機視覺庫OpenCV、三維可視化庫VTK、醫學圖像處理庫ITK。而Python專用的科學計算擴展庫就更多了,例如以下3個十分經典的科學計算擴展庫:NumPy、SciPy和matplotlib,它們分別爲Python提供了快速數組處理、數值運算以及繪圖功能。所以Python語言及其衆多的擴展庫所構成的開發環境十分適合工程技術、科研人員處理實驗數據、製做圖表,甚至開發科學計算應用程序。web

提及科學計算,首先會被提到的多是MATLAB。然而除了MATLAB的一些專業性很強的工具箱還沒法替代以外,MATLAB的大部分經常使用功能均可以在Python世界中找到相應的擴展庫。和MATLAB相比,用Python作科學計算有以下優勢:正則表達式

● 首先,MATLAB是一款商用軟件,而且價格不菲。而Python徹底免費,衆多開源的科學計算庫都提供了Python的調用接口。用戶能夠在任何計算機上免費安裝Python及其絕大多數擴展庫。算法

● 其次,與MATLAB相比,Python是一門更易學、更嚴謹的程序設計語言。它能讓用戶編寫出更易讀、易維護的代碼。sql

● 最後,MATLAB主要專一於工程和科學計算。然而即便在計算領域,也常常會遇到文件管理、界面設計、網絡通訊等各類需求。而Python有着豐富的擴展庫,能夠輕易完成各類高級任務,開發者能夠用Python實現完整應用程序所需的各類功能。

三、關鍵點常識

一、Python的發音與拼寫

二、Python的意思是蟒蛇,源於做者喜歡的一部電視劇 (C呢?)

三、Python的做者是Guido van Rossum(龜叔)

四、Python是龜叔在1989年聖誕節期間,爲了打發無聊的聖誕節而用C編寫的一個編程語言

五、Python正式誕生於1991年

六、 Python的解釋器現在有多個語言實現,咱們經常使用的是CPython(官方版本的C語言實現),七、其餘還有Jython(能夠運行在Java平臺)、IronPython(能夠運行在.NET和Mono平臺)、PyPy(Python實現的,支持JIT即時編譯)

八、Python目前有兩個版本,Python2和Python3,最新版分別爲2.7.13和3.6.2,現階段大部分公司用的是Python2,Life is shot, you need Python. 人生苦短,我用Python。

九、2018年8月份 編程語言用戶量排行榜 :https://www.tiobe.com/tiobe-index/

四、Python優缺點

l  簡單————Python是一種表明簡單主義思想的語言。閱讀一個良好的Python程序就感受像是在讀英語同樣,儘管這個英語的要求很是嚴格!Python的這種僞代碼本質是它最大的優勢之一。它使你可以專一於解決問題而不是去搞明白語言自己。

l  易學————就如同你即將看到的同樣,Python極其容易上手。前面已經提到了,Python有極其簡單的語法。

l  免費、開源————Python是FLOSS(自由/開放源碼軟件)之一。簡單地說,你能夠自由地發佈這個軟件的拷貝、閱讀它的源代碼、對它作改動、把它的一部分用於新的自由軟件中。FLOSS是基於一個團體分享知識的概念。這是爲何Python如此優秀的緣由之一——它是由一羣但願看到一個更加優秀的Python的人創造並常常改進着的。

l  高層語言————當你用Python語言編寫程序的時候,你無需考慮諸如如何管理你的程序使用的內存一類的底層細節。

l  可移植性————因爲它的開源本質,Python已經被移植在許多平臺上(通過改動使它可以工做在不一樣平臺上)。若是你當心地避免使用依賴於系統的特性,那麼你的全部Python程序無需修改就能夠在下述任何平臺上面運行。這些平臺包括Linux、Windows、FreeBSD、Macintosh、Solaris、OS/二、Amiga、AROS、AS/400、BeOS、OS/390、z/OS、Palm OS、QNX、VMS、Psion、Acom RISC OS、VxWorks、PlayStation、Sharp Zaurus、Windows CE甚至還有PocketPC、Symbian以及Google基於linux開發的Android平臺!

l  解釋性————這一點須要一些解釋。一個用編譯性語言好比C或C++寫的程序能夠從源文件(即C或C++語言)轉換到一個你的計算機使用的語言(二進制代碼,即0和1)。這個過程經過編譯器和不一樣的標記、選項完成。當你運行你的程序的時候,鏈接/轉載器軟件把你的程序從硬盤複製到內存中而且運行。而Python語言寫的程序不須要編譯成二進制代碼。你能夠直接從源代碼運行程序。在計算機內部,Python解釋器把源代碼轉換成稱爲字節碼的中間形式,而後再把它翻譯成計算機使用的機器語言並運行。事實上,因爲你再也不須要擔憂如何編譯程序,如何確保鏈接轉載正確的庫等等,全部這一切使得使用Python更加簡單。因爲你只須要把你的Python程序拷貝到另一臺計算機上,它就能夠工做了,這也使得你的Python程序更加易於移植。

l  面向對象————Python既支持面向過程的編程也支持面向對象的編程。在「面向過程」的語言中,程序是由過程或僅僅是可重用代碼的函數構建起來的。在「面向對象」的語言中,程序是由數據和功能組合而成的對象構建起來的。與其餘主要的語言如C++和Java相比,Python以一種很是強大又簡單的方式實現面向對象編程。

l  可擴展性————若是你須要你的一段關鍵代碼運行得更快或者但願某些算法不公開,你能夠把你的部分程序用C或C++編寫,而後在你的Python程序中使用它們。

l  豐富的庫————Python標準庫確實很龐大。它能夠幫助你處理各類工做,包括正則表達式、文檔生成、單元測試、線程、數據庫、網頁瀏覽器、CGI、FTP、電子郵件、XML、XML-RPC、HTML、WAV文件、密碼系統、GUI(圖形用戶界面)、Tk和其餘與系統有關的操做。記住,只要安裝了Python,全部這些功能都是可用的。這被稱做Python的「功能齊全」理念。除了標準庫之外,還有許多其餘高質量的庫,如wxPython、Twisted和Python圖像庫等等。

l  規範的代碼————Python採用強制縮進的方式使得代碼具備極佳的可讀性。

 

五、Python應用場景

l  Web應用開發

Python常常被用於Web開發。好比,經過mod_wsgi模塊,Apache能夠運行用Python編寫的Web程序。Python定義了WSGI標準應用接口來協調Http服務器與基於Python的Web程序之間的通訊。一些Web框架,如Django,TurboGears,web2py,Zope等,可讓程序員輕鬆地開發和管理複雜的Web程序。

l  操做系統管理、服務器運維的自動化腳本

在不少操做系統裏,Python是標準的系統組件。 大多數Linux發行版以及NetBSD、OpenBSD和Mac OS X都集成了Python,能夠在終端下直接運行Python。有一些Linux發行版的安裝器使用Python語言編寫,好比Ubuntu的Ubiquity安裝器,Red Hat Linux和Fedora的Anaconda安裝器。Gentoo Linux使用Python來編寫它的Portage包管理系統。Python標準庫包含了多個調用操做系統功能的庫。經過pywin32這個第三方軟件 包,Python可以訪問Windows的COM服務及其它Windows API。使用IronPython,Python程序可以直接調用.Net Framework。通常說來,Python編寫的系統管理腳本在可讀性、性能、代碼重用度、擴展性幾方面都優於普通的shell腳本。

l  科學計算機器學習

NumPy,SciPy,Matplotlib可讓Python程序員編寫科學計算程序。

l  服務器軟件(網絡軟件)——阿里雲

Python對於各類網絡協議的支持很完善,所以常常被用於編寫服務器軟件、網絡爬蟲。第三方庫Twisted支持異步網絡編程和多數標準的網絡協議(包含客戶端和服務器),而且提供了多種工具,被普遍用於編寫高性能的服務器軟件。

 

第二章 python安裝下載及基礎語法

一、Python的下載

       一、python網址:https://www.python.org/

       二、anaconda網址:https://www.anaconda.com/

注意:Anaconda指的是一個開源的Python發行版本,其包含了conda、Python等180多個科學包及其依賴項。

二、Python的安裝

       一、Python安裝比較簡單,只須要雙擊安裝便可,安裝比較快(window)

       二、anaconda一樣是雙擊安裝,可是安裝過程的時間比較長,須要不少依賴項(window)

三、Python IDE的安裝

       一、eclipse插件安裝

              Help—> eclipse marketplace—> pydev(較慢)

              插件包:加壓拷貝到eclipse的dropins中,重啓便可

       二、pycharm安裝

              傻瓜式安裝,建立新的項目的時候直接選擇sdk

四、第一個案例程序Python_helloworld

       一、在任意的IDE中建立Python項目

       二、建立Python file文件

       三、輸入代碼 print(「hello ,python」)

       四、右擊直接運行,會在控制檯看到對應的結果

五、交互式窗口

       一、python:在cmd中直接輸入python(配置環境變量)

       二、ipython:找到對應的ipython的執行文件,直接執行

              Ipython:支持變量自動補全,自動縮進,支持 bash shell 命令,內置了許多頗有用的功能和函數

              注意:Python中自己不帶有這個ipython的交互,須要自行安裝。首先查看計算機中是否包含pip,通常安裝完以後有,執行python –m pip install –upgrade pip,先將pip進行更新,而後安裝ipython:pip install ipython

六、Python的註釋及亂碼

       一、單行註釋:以#開頭,#右邊的全部東西當作說明,而不是真正要執行的程序,起輔助說明做用

       二、多行註釋:’’’多行註釋’’’能夠寫多行的功能說明

       三、Python亂碼問題

          因爲Python源代碼也是一個文本文件,因此,當你的源代碼中包含中文的時候,在保存源代碼時,就須要務必指定保存爲UTF-8編碼。當Python解釋器讀取源代碼時,爲了讓它按UTF-8編碼讀取,咱們一般在文件開頭寫上這兩行:

       # -*- coding:utf-8 -*-

       # coding=utf-8

七、變量及類型

       一、變量的定義

在程序中,有時咱們須要對2個數據進行求和,那麼該怎樣作呢?

你們類比一下現實生活中,好比去超市買東西,每每我們須要一個菜籃子,用來進行存儲物品,等到全部的物品都購買完成後,在收銀臺進行結帳便可

若是在程序中,須要把2個數據,或者多個數據進行求和的話,那麼就須要把這些數據先存儲起來,而後把它們累加起來便可

在Python中,存儲一個數據,須要一個叫作變量的東西:

例如: num1=100

         Num2=87

         Result=num1+num2

變量三要素:變量的名稱,變量的類型,變量的值

二、變量的類型

爲了更充分的利用內存空間以及更有效率的管理內存,變量是有不一樣的類型,如圖所示

 

       注意:

              整數

Python能夠處理任意大小的整數,固然包括負整數,在程序中的表示方法和數學上的寫法如出一轍,例如:1,100,-8080,0,等等。

計算機因爲使用二進制,因此,有時候用十六進制表示整數比較方便,十六進制用0x前綴和0-9,a-f表示,例如:0xff00,0xa5b4c3d2,等等。

浮點數

浮點數也就是小數,之因此稱爲浮點數,是由於按照科學記數法表示時,一個浮點數的小數點位置是可變的,好比,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()打印字符串看看:

若是字符串裏面有不少字符都須要轉義,就須要加不少\,爲了簡化,Python還容許用r''表示''內部的字符串默認不轉義,能夠本身試試:

若是字符串內部有不少換行,用\n寫在一行裏很差閱讀,爲了簡化,Python容許用'''...'''的格式表示多行內容,

print('''line1

line2

line3''')

布爾值

布爾值和布爾代數的表示徹底一致,一個布爾值只有True、False兩種值,要麼是True,要麼是False,在Python中,能夠直接用True、False表示布爾值(請注意大小寫),也能夠經過布爾運算計算出來

布爾值能夠用and、or和not運算。

and運算是與運算,只有全部都爲True,and運算結果纔是True:

空值

空值是Python裏一個特殊的值,用None表示。None不能理解爲0,由於0是有意義的,而None是一個特殊的空值。

此外,Python還提供了列表、字典等多種數據類型,還容許建立自定義數據類型,咱們後面會繼續講到。

怎樣知道一個變量的類型呢?

在python中,只要定義了一個變量,並且它有數據,那麼它的類型就已經肯定了,不須要我們開發者主動的去說明它的類型,系統會自動辨別

能夠使用type(變量的名字),來查看變量的類型

 

       三、常見的數據類型轉換

 

函數

說明

int(x [,base ])

將x轉換爲一個整數

long(x [,base ])

將x轉換爲一個長整數

float(x )

將x轉換到一個浮點數

complex(real [,imag ])

建立一個複數

str(x )

將對象 x 轉換爲字符串

repr(x )

將對象 x 轉換爲表達式字符串

eval(str )

用來計算在字符串中的有效Python表達式,並返回一個對象

tuple(s )

將序列 s 轉換爲一個元組

list(s )

將序列 s 轉換爲一個列表

chr(x )

將一個整數轉換爲一個字符

unichr(x )

將一個整數轉換爲Unicode字符

ord(x )

將一個字符轉換爲它的整數值

hex(x )

將一個整數轉換爲一個十六進制字符串

oct(x )

將一個整數轉換爲一個八進制字符串

八、標識符和關鍵字

       一、標識符

開發人員在程序中自定義的一些符號和名稱,標示符是本身定義的,如變量名 、函數名等

 

二、標示符的規則

標示符由字母、下劃線和數字組成,且數字不能開頭。不能有特殊符號:\,/,;,#

思考:下面的標示符哪些是正確的,哪些不正確爲何

fromNo12 from#12 my_Boolean my-Boolean Obj2 2ndObj myInt test1 Mike2jack My_tExt _test test!32haha(da)ttint jack_rose jack&rose GUI G.U.I

python中的標識符是區分大小寫的

 

三、命名規則

見名知意

起一個有意義的名字,儘可能作到看一眼就知道是什麼意思(提升代碼可 讀性) 好比: 名字 就定義爲 name , 定義學生 用 student

駝峯命名法 : 

 

小駝峯式命名法(lower camel case): 第一個單詞以小寫字母開始;第二個單詞的首字母大寫,例如:myName、aDog  

大駝峯式命名法(upper camel case): 每個單字的首字母都採用大寫字母,例如:FirstName、LastName

不過在程序員中還有一種命名法比較流行,就是用下劃線「_」來鏈接全部的單詞,好比send_buf

       四、關鍵字

python一些具備特殊功能的標示符,這就是所謂的關鍵字

關鍵字,是python已經使用的了,因此不容許開發者本身定義和關鍵字相同的名字的標示符

查看關鍵字:(保留字)

And      as         assert          break            class            continue def      

del        elif               else              except          exec      finally    for

from     global   if                  in                 import is           lambda

not               or          pass             print             raise      return     try

while    with      yield

能夠經過如下命令進行查看當前系統中python的關鍵字:

import keyword

keyword.kwlist

 

九、輸入與輸出

       一、普通的輸出

 

# 打印提示

    print('hello world') System.out.println

用print()在括號中加上字符串,就能夠向屏幕上輸出指定的文字。好比輸出'hello, world',用代碼實現以下:

>>> print('hello, world')

 

print()函數也能夠接受多個字符串,用逗號「,」隔開,就能夠連成一串輸出:

>>> print('The quick brown fox', 'jumps over', 'the lazy dog')

The quick brown fox jumps over the lazy dog

 

print()會依次打印每一個字符串,遇到逗號「,」會輸出一個空格,所以,輸出的字符串是這樣拼起來的:

 

print()也能夠打印整數,或者計算結果:

>>> print(300)

300>>> print(100 + 200)

300

所以,咱們能夠把計算100 + 200的結果打印得更漂亮一點:

>>> print('100 + 200 =', 100 + 200)

100 + 200 = 300

注意,對於100 + 200,Python解釋器自動計算出結果300,可是,'100 + 200 ='是字符串而非數學公式,Python把它視爲字符串,請自行解釋上述打印結果。

 

二、格式化輸出

      

最後一個常見的問題是如何輸出格式化的字符串。咱們常常會輸出相似'親愛的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'

有些時候,字符串裏面的%是一個普通字符怎麼辦?這個時候就須要轉義,用%%來表示一個%:

>>> 'growth rate: %d %%' % 7

'growth rate: 7 %'

練習:編寫程序

小明的成績從去年的72分提高到了今年的85分,請計算小明成績提高的百分點,並用字符串格式化顯示出'xx.x%',只保留小數點後1位:

三、輸入

若是要讓用戶從電腦輸入一些字符怎麼辦?Python提供了一個input(),可讓用戶輸入字符串,並存放到一個變量裏

1. python2版本中

1.1 raw_input()

在Python中,獲取鍵盤輸入的數據的方法是採用 raw_input 函數。

看以下示例:

注意:

raw_input()的小括號中放入的是,提示信息,用來在獲取數據以前給用戶的一個簡單提示

raw_input()在從鍵盤獲取了數據之後,會存放到等號右邊的變量中

raw_input()會把用戶輸入的任何值都做爲字符串來對待

1.2 input()

input()函數與raw_input()相似,但其接受的輸入做爲是表達式。

input()接受表達式輸入,並把表達式的結果賦值給等號左邊的變量

raw_input()輸入的都當成字符串(和Python3的input功能同樣)

2. python3版本中

沒有raw_input()函數,只有input()

而且 python3中的input與python2中的raw_input()功能同樣

十、運算符

一、算術運算符

下面以a=10 ,b=20爲例進行計算

運算符

描述

實例

+

兩個對象相加 a + b 輸出結果 30

-

獲得負數或是一個數減去另外一個數 a - b 輸出結果 -10

*

兩個數相乘或是返回一個被重複若干次的字符串 a * b 輸出結果 200

/

x除以y b / a 輸出結果 2

//

取整除

返回商的整數部分 9//2 輸出結果 4 , 9.0//2.0 輸出結果 4.0

%

取餘(取模)

返回除法的餘數 b % a 輸出結果 0

**

返回x的y次冪 a**b 爲10的20次方, 輸出結果 100000000000000000000

>>> 9/2.0

4.5

>>> 9//2.0

4.0

二、賦值運算符

運算符

描述

實例

=

賦值運算符

把=號右邊的結果給左邊的變量 num=1+2*3 結果num的值爲7

>>> a, b = 1, 2

>>> a

1

>>> b

2

三、複合賦值運算符

 

運算符

描述

實例

+=

加法賦值運算符

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

       注意:Python中沒有a++,a--,++a,--a等操做

       四、邏輯運算符

運算符

邏輯表達式

描述

實例

and 

x and y

布爾"與" - 若是 x 爲 False,x and y 返回 False,不然它返回 y 的計算值。

(a and b) 返回 20。

or

x or y

布爾"或" - 若是 x 是 True,它返回 True,不然它返回 y 的計算值。

(a or b) 返回 10。

not

not x

布爾"非" - 若是 x 爲 True,返回 False 。若是 x 爲 False,它返回 True。

not(a and b) 返回 False

      

 

 

 

五、比較(關係)運算符

運算符

描述

示例

==

檢查兩個操做數的值是否相等,若是是則條件變爲真。

如a=3,b=3則(a == b) 爲 true.

!=

檢查兩個操做數的值是否相等,若是值不相等,則條件變爲真。

如a=1,b=3則(a != b) 爲 true.

<> 

檢查兩個操做數的值是否相等,若是值不相等,則條件變爲真。

如a=1,b=3則(a <> b) 爲 true。這個相似於 != 運算符

檢查左操做數的值是否大於右操做數的值,若是是,則條件成立。

如a=7,b=3則(a > b) 爲 true.

檢查左操做數的值是否小於右操做數的值,若是是,則條件成立。

如a=7,b=3則(a < b) 爲 false.

>=

檢查左操做數的值是否大於或等於右操做數的值,若是是,則條件成立。

如a=3,b=3則(a >= b) 爲 true.

<=

檢查左操做數的值是否小於或等於右操做數的值,若是是,則條件成立。

如a=3,b=3則(a <= b) 爲 true.

 

練習:

    由用輸入一個學生的信息,(姓名,年齡,地址)。而後看看年齡是不是偶數,而後輸出。

第三章 Python的邏輯判斷和循環

一、if elif else條件判斷

計算機之因此能作不少自動化的任務,由於它能夠本身作條件判斷。

elif是else if的縮寫,徹底能夠有多個elif,因此if語句的完整形式就是:

if <條件判斷1>:

    <執行1>

elif <條件判斷2>:

    <執行2>

elif <條件判斷3>:

    <執行3>

else:

    <執行4>

 

好比,輸入用戶年齡,根據年齡打印不一樣的內容,在Python程序中,用if語句實現:

age = 20

if age >= 18:

    print('your age is', age)

    print('adult')

 

根據Python的縮進規則,若是if語句判斷是True,就把縮進的兩行print語句執行了,不然,什麼也不作。

也能夠給if添加一個else語句,意思是,若是if判斷是False,不要執行if的內容,去把else執行了:

age = 3

if age >= 18:

    print('your age is', age)

    print('adult')

else:

    print('your age is', age)

    print('teenager')

 

注意不要少寫了冒號:。

固然上面的判斷是很粗略的,徹底能夠用elif作更細緻的判斷:

age = 3

if age >= 18:

    print('adult')

elif age >= 6:

    print('teenager')

else:

    print('kid')

 

if判斷條件還能夠簡寫,好比寫:

if x:

    print('True')

 

只要x是非零數值、非空字符串、非空list等,就判斷爲True,不然爲False。

 

二、input陷阱

最後看一個有問題的條件判斷。不少同窗會用input()讀取用戶的輸入,這樣能夠本身輸入,程序運行得更有意思:

birth = input('birth: ')

if birth < 2000:

    print('00前')

else:

    print('00後')

輸入1982,結果報錯:

這是由於input()返回的數據類型是str,str不能直接和整數比較,必須先把str轉換成整數。Python提供了int()函數來完成這件事情:

s = input('birth: ')

birth = int(s)

if birth < 2000:

    print('00前')

else:

    print('00後')

 

再次運行,就能夠獲得正確地結果。可是,若是輸入abc呢?又會獲得一個錯誤信息:

Traceback (most recent calllast):

  File "<stdin>", line 1, in <module>

ValueError: invalid literal forint() with base 10: 'abc'

原來int()函數發現一個字符串並非合法的數字時就會報錯,程序就退出了。

如何檢查並捕獲程序運行期的錯誤呢?後面的錯誤和調試會講到。

三、if嵌套的格式

if 條件1:

知足條件1 作的事情1

知足條件1 作的事情2

...(省略)...

if 條件2:

知足條件2 作的事情1

知足條件2 作的事情2

...(省略)...

說明:

外層的if判斷,也能夠是if-else

內層的if判斷,也能夠是if-else

根據實際開發的狀況,進行選擇

 

練習

一、要求:從鍵盤輸入刀子的長度,若是刀子長度沒有超過10cm,則容許上火車,不然不容許上火車

二、 

二、小明身高1.75,體重80.5kg。請根據BMI公式(體重除以身高的平方)幫小明計算他的BMI指數,並根據BMI指數:

低於18.5:太輕

18.5-25:正常

25-28:太重

28-32:肥胖

高於32:嚴重肥胖

用if-elif判斷並打印結果:

 

三、情節描述:上公交車,而且能夠有座位坐下

要求:輸入公交卡當前的餘額,只要超過2元,就能夠上公交車;若是空座位的數量大於0,就能夠坐下

四、循環結構

       一、循環介紹

要計算1+2+3,咱們能夠直接寫表達式:

>>> 1 + 2 + 3=6

要計算1+2+3+...+10,勉強也能寫出來。

可是,要計算1+2+3+...+10000,直接寫表達式就不可能了。

爲了讓計算機能計算成千上萬次的重複運算,咱們就須要循環語句。

Python的循環有兩種,一種是for...in循環,另一種是while循環。

二、while循環

while循環的格式

while 條件:

        條件知足時,作的事情1

        條件知足時,作的事情2

        條件知足時,作的事情3

        ...(省略)...

pass 和while沒有關係

while循環應用

1. 計算1~100的累積和(包含1和100)

參考代碼以下:

#encoding=utf-8

i = 1

sum = 0

while i<=100:

    sum = sum + i

    i += 1

print("1~100的累積和爲:%d"%sum)

 

2. 計算1~100之間偶數的累積和(包含1和100)

一、循環次數(while中循環次數由條件決定)

二、在循環過程當中作什麼

三、變量怎麼變化?

       三、while循環嵌套

前面學習過if的嵌套了,想想if嵌套是什麼樣子的?

相似if的嵌套,while嵌套就是:while裏面還有while

<1>while嵌套的格式

while 條件1:

        條件1知足時,作的事情1

        條件1知足時,作的事情2

        條件1知足時,作的事情3

        ...(省略)...

        while 條件2:

            條件2知足時,作的事情1

            條件2知足時,作的事情2

            條件2知足時,作的事情3

            ...(省略)...

<2>while嵌套應用一

要求:打印以下圖形: m行,每行打印n次,n==m

*

* *

* * *

* * * *

* * * * *

<3>while嵌套應用二:九九乘法表

 

 

       四、for循環

像while循環同樣,for能夠完成循環的功能。

在Python中 for循環能夠遍歷任何序列的項目,如一個列表或者一個字符串等。

for循環的格式

for 臨時變量 in 列表或者字符串等:

        循環知足條件時執行的代碼

    else:

        循環不知足條件時執行的代碼

五、break和continue

一、break

在循環中,break語句能夠提早退出循環。例如,原本要循環打印1~100的數字:

n = 1

while n <=100:

print(n)

n = n + 1

print('END')

上面的代碼能夠打印出1~100。

若是要提早結束循環,能夠用break語句:

n = 1

while n <= 100:

if n > 10: # 當n = 11時,條件知足,執行break語句

break # break語句會結束當前循環print(n)

n = n + 1

print('END')

 

執行上面的代碼能夠看到,打印出1~10後,緊接着打印END,程序結束。

可見break的做用是提早結束循環。

二、continue

在循環過程當中,也能夠經過continue語句,跳過當前的此次循環,直接開始下一次循環。

n = 0

while n < 10:

n = n + 1

print(n)

上面的程序能夠打印出1~10。可是,若是咱們想只打印奇數,能夠用continue語句跳過某些循環:

n = 0

while n < 10:

    n = n + 1

    if n % 2 == 0: # 若是n是偶數,執行continue語句continue# continue語句會直接繼續下一輪循環,後續的print()語句不會執行print(n)

 

執行上面的代碼能夠看到,打印的再也不是1~10,而是1,3,5,7,9。

可見continue的做用是提早結束本輪循環,並直接開始下一輪循環。

 

六、小結

循環是讓計算機作重複任務的有效的方法。

break語句能夠在循環過程當中直接退出循環,而continue語句能夠提早結束本輪循環,並直接開始下一輪循環。這兩個語句一般都必須配合if語句使用。

要特別注意,不要濫用break和continue語句。break和continue會形成代碼執行邏輯分叉過多,容易出錯。大多數循環並不須要用到break和continue語句,上面的兩個例子,均可以經過改寫循環條件或者修改循環邏輯,去掉break和continue語句。

有些時候,若是代碼寫得有問題,會讓程序陷入「死循環」,也就是永遠循環下去。這時能夠用Ctrl+C退出程序,或者強制結束Python進程。

第四章 集合類型

一、字符串

       一、下標索引

       所謂下標,就是編號,就比如超市中的存儲櫃的編號,經過這個編號就能找到相應的存儲空間

       字符串實際上就是字符的數組,因此也支持下標索引。

若是有字符串:name = 'abcdef',在內存中的實際存儲以下:

 

若是想取出部分字符,那麼能夠經過下標的方法,(注意python中下標從 0 開始)

   name = 'abcdef'

   print(name[0])

   print(name[1])

   print(name[-2])

二、切片(分片)

切片是指對操做的對象截取其中一部分的操做。字符串、列表、元組都支持切片操做。

切片的語法:[起始:結束:步長]

步長:表示下標變化的規律。

注意:選取的區間屬於左閉右開型,即從"起始"位開始,到"結束"位的前一位結束(不包含結束位自己)。

咱們以字符串爲例講解。

若是取出一部分,則能夠在中括號[]中,使用:

name = 'abcdef'

print(name[0:3]) # 取 下標0~2 的字符

name = 'abcdef'

print(name[0:5]) # 取 下標爲0~4 的字符

name = 'abcdef'

print(name[3:5]) # 取 下標爲三、4 的字符

name = 'abcdef'

print(name[2:]) # 取 下標爲2開始到最後的字符

name = 'abcdef'

print(name[1:-1]) # 取 下標爲1開始 到 最後第2個  之間的字符

>>> a = "abcdef"

>>> a[:3]

'abc'

>>> a[::2]

'ace'

>>> a[5:1:2]

''

>>> a[1:5:2]

'bd'

>>> a[::-2]

'fdb'

>>> a[5:1:-2]

'fd'

三、字符串常見操做

       若有字符串mystr = 'hello world and bjsxt yunshuxueyuan sxt beijing',如下是常見的操做

<1>find == java Indexof方法

檢測 str 是否包含在 mystr中,若是是返回開始的索引值,不然返回-1

mystr.find(str, start=0, end=len(mystr))

<2>index

跟find()方法同樣,只不過若是str不在 mystr中會報一個異常.

mystr.index(str, start=0, end=len(mystr))

<3>count

返回 str在start和end之間 在 mystr裏面出現的次數

mystr.count(str, start=0, end=len(mystr))

<4>replace

把 mystr 中的 str1 替換成 str2,若是 count 指定,則替換不超過 count 次.

mystr.replace(str1, str2,  mystr.count(str1))

<5>split

以 str 爲分隔符切片 mystr,若是 maxsplit有指定值,則僅分隔 maxsplit 個子字符串

mystr.split(str=" ", 2)   

<6>capitalize

把字符串的第一個字符大寫

mystr.capitalize()

<7>title

把字符串的每一個單詞首字母大寫

<8>startswith

檢查字符串是不是以 obj 開頭, 是則返回 True,不然返回 False

mystr.startswith(obj)

<9>endswith

檢查字符串是否以obj結束,若是是返回True,不然返回 False.

mystr.endswith(obj)

<10>lower

轉換 mystr 中全部大寫字符爲小寫

mystr.lower()       

<11>upper

轉換 mystr 中的小寫字母爲大寫

mystr.upper()   

<12>ljust

返回一個原字符串左對齊,並使用空格填充至長度 width 的新字符串

mystr.ljust(width)

<13>rjust

返回一個原字符串右對齊,並使用空格填充至長度 width 的新字符串

mystr.rjust(width)   

<14>center

返回一個原字符串居中,並使用空格填充至長度 width 的新字符串

mystr.center(width)  

<15>lstrip

刪除 mystr 左邊的空白字符

mystr.lstrip()

<16>rstrip

刪除 mystr 字符串末尾的空白字符

mystr.rstrip()   

<17>strip ---java trim

刪除mystr字符串兩端的空白字符

<18>rfind

相似於 find()函數,不過是從右邊開始查找.

mystr.rfind(str, start=0,end=len(mystr) )

<19>rindex

相似於 index(),不過是從右邊開始.

mystr.rindex( str, start=0,end=len(mystr))

<20>partition

把mystr以str分割成三部分,str前,str和str後

mystr.partition(str)

<21>rpartition

相似於 partition()函數,不過是從右邊開始.

mystr.rpartition(str)

<22>splitlines

按照換行符分隔,返回一個包含各行做爲元素的列表

mystr.splitlines() 

<23>isalpha

若是 mystr 全部字符都是字母 則返回 True,不然返回 False

mystr.isalpha() 

<24>isdigit

若是 mystr 只包含數字則返回 True 不然返回 False.

mystr.isdigit()

<25>isalnum

若是 mystr 全部字符都是字母或數字則返回 True,不然返回 False

mystr.isalnum() 

<26>isspace

若是 mystr 中只包含空格,則返回 True,不然返回 False.

mystr.isspace()  

<27>join

mystr 中每一個字符後面插入list的每一個元素後面,構造出一個新的字符串

mystr.join(list)

總結:

    查找字符串:

    find:找不到返回-1   ,都是從左邊找,右邊查找r

    index:找不到報錯

二、列表

1、列表介紹

Python內置的一種數據類型是列表:list。list是一種有序的集合,能夠隨時添加和刪除其中的元素。

好比,列出班裏全部同窗的名字,就能夠用一個list表示:

>>> classmates = ['Michael', 'Bob', 'Tracy']

>>> classmates

['Michael', 'Bob', 'Tracy']

 

變量classmates就是一個list。用len()函數能夠得到list元素的個數:

>>> len(classmates)

3

用索引來訪問list中每個位置的元素,記得索引是從0開始的:

>>> classmates[0]

'Michael'

>>> classmates[1]

'Bob'

>>> classmates[2]

'Tracy'

>>> classmates[3]

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

IndexError: list index out of range

當索引超出了範圍時,Python會報一個IndexError錯誤,因此,要確保索引不要越界,記得最後一個元素的索引是len(classmates) - 1。

若是要取最後一個元素,除了計算索引位置外,還能夠用-1作索引,直接獲取最後一個元素:

>>> classmates[-1]

'Tracy'

以此類推,能夠獲取倒數第2個、倒數第3個:

2、列表的相關操做

列表中存放的數據是能夠進行修改的,好比"增"、"刪"、"改""

<1>添加元素("增"append, extend, insert)

append

經過append能夠向列表添加元素

extend(+)

經過extend能夠將另外一個集合中的元素逐一添加到列表中

      

>>> a = [1, 2]

>>> b = [3, 4]

>>> a.append(b)

>>> a

[1, 2, [3, 4]]

>>> a.extend(b)

>>> a

[1, 2, [3, 4], 3, 4]

 

insert

insert(index, object) 在指定位置index前插入元素object

>>> a = [0, 1, 2]

>>> a.insert(1, 3)

>>> a

[0, 3, 1, 2]

 

<2>修改元素("改")

修改元素的時候,要經過下標來肯定要修改的是哪一個元素,而後才能進行修改

<3>查找元素("查"in, not in, index, count)

所謂的查找,就是看看指定的元素是否存在

in, not in

python中查找的經常使用方法爲:

in(存在),若是存在那麼結果爲true,不然爲false

not in(不存在),若是不存在那麼結果爲true,不然false

#查找是否存在if findName in nameList:

        print('在字典中找到了相同的名字')

    else:

        print('沒有找到')

說明:

in的方法只要會用了,那麼not in也是一樣的用法,只不過not in判斷的是不存在

index, count

index和count與字符串中的用法相同

>>> a = ['a', 'b', 'c', 'a', 'b']

>>> a.index('a', 1, 3) # 注意是左閉右開區間

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

ValueError: 'a'isnotin list

>>> a.index('a', 1, 4)

3>>> a.count('b')

2>>> a.count('d')

0

<4>刪除元素("刪"del, pop, remove)

類比現實生活中,若是某位同窗調班了,那麼就應該把這個條走後的學生的姓名刪除掉;在開發中常常會用到刪除這種功能。

列表元素的經常使用刪除方法有:

del:根據下標進行刪除,其實能夠刪除全部變量

pop:默認刪除最後一個元素

remove:根據元素的值進行刪除第一個

>>> l

['abcdef', ['aaa', 'bb', 'ccc'], 'ddd', 'fff']

>>> del  l[0]

>>> l

[['aaa', 'bb', 'ccc'], 'ddd', 'fff']

<5>排序(sort, reverse)

sort方法是將list按特定順序從新排列,默認爲由小到大,參數reverse=True可改成倒序,由大到小。

reverse方法是將list逆置。

>>> a = [1, 4, 2, 3]

>>> a

[1, 4, 2, 3]

>>> a.reverse()

>>> a

[3, 2, 4, 1]

>>> a.sort()

>>> a

[1, 2, 3, 4]

>>> a.sort(reverse=True)

>>> a

[4, 3, 2, 1]

<6>enumerate()

>>> chars = ['a', 'b', 'c', 'd']

>>> for i, chr in enumerate(chars):

...     print i, chr

...

0 a

1 b

2 c

3 d

 

三、元組

       Python的元組與列表相似,不一樣之處在於元組的元素不能修改。元組使用小括號,列表使用方括號。

>>> aTuple = ('et',77,99.9)

>>> aTuple ('et',77,99.9)

若是要定義一個空的tuple,能夠寫成():

>>> t = ()

>>> t ()

可是,要定義一個只有1個元素的tuple,若是你這麼定義:

>>> t = (1)

>>> t 1

定義的不是tuple,是1這個數!這是由於括號()既能夠表示tuple,又能夠表示數學公式中的小括號,這就產生了歧義,所以,Python規定,這種狀況下,按小括號進行計算,計算結果天然是1。

因此,只有1個元素的tuple定義時必須加一個逗號,,來消除歧義:

>>> t = (1,)

>>> t (1,)

Python在顯示只有1個元素的tuple時,也會加一個逗號,,以避免你誤解成數學計算意義上的括號。

最後來看一個「可變的」tuple:

>>> t = ('a', 'b', ['A', 'B'])

>>> t[2][0] = 'X'

>>> t[2][1] = 'Y'

>>> t ('a', 'b', ['X', 'Y'])

這個tuple定義的時候有3個元素,分別是'a','b'和一個list。不是說tuple一旦定義後就不可變了嗎?怎麼後來又變了?

別急,咱們先看看定義的時候tuple包含的3個元素:

 

當咱們把list的元素'A'和'B'修改成'X'和'Y'後,tuple變爲:

 

表面上看,tuple的元素確實變了,但其實變的不是tuple的元素,而是list的元素。tuple一開始指向的list並無改爲別的list,因此,tuple所謂的「不變」是說,tuple的每一個元素,指向永遠不變。即指向'a',就不能改爲指向'b',指向一個list,就不能改爲指向其餘對象,但指向的這個list自己是可變的!

理解了「指向不變」後,要建立一個內容也不變的tuple怎麼作?那就必須保證tuple的每個元素自己也不能變。

<1>訪問元組

 

<2>修改元組

 

說明: python中不容許修改元組的數據,包括不能刪除其中的元素。

<3>元組的內置函數count, index

index和count與字符串和列表中的用法相同

>>> a = ('a', 'b', 'c', 'a', 'b')

>>> a.index('a', 1, 3) # 注意是左閉右開區間

Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: tuple.index(x): x notin tuple

>>> a.index('a', 1, 4)

 3

>>> a.count('b')

 2

>>> a.count('d')

0

四、字典

       一、字典的介紹

Python內置了字典:dict的支持,dict全稱dictionary,在其餘語言中也稱爲map,使用鍵-值(key-value)存儲,具備極快的查找速度。

舉個例子,假設要根據同窗的名字查找對應的成績,若是用list實現,須要兩個list:

names = ['Michael', 'Bob', 'Tracy']

scores = [95, 75, 85]

給定一個名字,要查找對應的成績,就先要在names中找到對應的位置,再從scores取出對應的成績,list越長,耗時越長。

若是用dict實現,只須要一個「名字」-「成績」的對照表,直接根據名字查找成績,不管這個表有多大,查找速度都不會變慢。用Python寫一個dict以下:

>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

>>> d['Michael']

95

軟件開發中的字典

變量info爲字典類型:

    info = {'name':'班長', 'id':100, 'sex':'f', 'address':'地球亞洲中國北京'}

說明:

l  字典和列表同樣,也可以存儲多個數據

l  列表中找某個元素時,是根據下標進行的

l  字典中找某個元素時,是根據'名字'(就是冒號:前面的那個值,例如上面代碼中的'name'、'id'、'sex')

l  字典的每一個元素由2部分組成,鍵:值。例如 'name':'班長' ,'name'爲鍵,'班長'爲值

若訪問不存在的鍵,則會報錯:

>>> info['age']

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

KeyError: 'age'

在咱們不肯定字典中是否存在某個鍵而又想獲取其值時,能夠使用get方法,還能夠設置默認值:

>>> age = info.get('age')

>>> age #'age'鍵不存在,因此age爲None>>> type(age)

<type 'NoneType'>

>>> age = info.get('age', 18) # 若info中不存在'age'這個鍵,就返回默認值18

>>> age

18

二、字典的常見操做

<1>修改元素

字典的每一個元素中的數據是能夠修改的,只要經過key找到,便可修改

demo:

info = {'name':'班長', 'id':100, 'sex':'f', 'address':'地球亞洲中國北京'}

newId = input('請輸入新的學號')

info['id'] = int(newId)

print('修改以後的id爲%d:'%info['id']

<2>添加元素

demo:訪問不存在的元素 

info = {'name':'班長', 'sex':'f', 'address':'地球亞洲中國北京'}

print('id爲:%d'%info['id'])

結果:

 

若是在使用 變量名['鍵'] = 數據 時,這個「鍵」在字典中,不存在,那麼就會新增這個元素

demo:添加新的元素

  

info = {'name':'班長', 'sex':'f', 'address':'地球亞洲中國北京'}

# print('id爲:%d'%info['id'])#程序會終端運行,由於訪問了不存在的鍵

newId = input('請輸入新的學號')

info['id'] = newId

print('添加以後的id爲:%d'%info['id'])

結果: 

請輸入新的學號188

添加以後的id爲: 188

<3>刪除元素

對字典進行刪除操做,有一下幾種:

del

clear()

demo:del刪除指定的元素

info = {'name':'班長', 'sex':'f', 'address':'地球亞洲中國北京'}

print('刪除前,%s'%info['name'])

del info['name']

print('刪除後,%s'%info['name'])

demo:del刪除整個字典

info = {'name':'monitor', 'sex':'f', 'address':'China'}

print('刪除前,%s'%info)

del info

print('刪除後,%s'%info)

demo:clear清空整個字典

三、字典的常見函數:

<1>len()

測量字典中,鍵值對的個數

<2>keys == map.keySet()

返回一個包含字典全部KEY的列表

<3>values

返回一個包含字典全部value的列表

<4>items

返回一個包含全部(鍵,值)元祖的列表

<5>has_key (python2.7版本) == in 條件表達式

dict.has_key(key)若是key在字典中,返回True,不然返回False

四、字典遍歷

<1> 遍歷字典的key(鍵)

 

<2> 遍歷字典的value(值)

 

<3> 遍歷字典的項(元素)

 

<4> 遍歷字典的key-value(鍵值對)

 

六、總結:

一、請務必注意,dict內部存放的順序和key放入的順序是沒有關係的。

二、和list比較,dict有如下幾個特色:

1)查找和插入的速度極快,不會隨着key的增長而變慢;

2)須要佔用大量的內存,內存浪費多。

3)而list相反:查找和插入的時間隨着元素的增長而增長;佔用空間小,浪費內存不多。

因此,dict是用空間來換取時間的一種方法。

三、dict能夠用在須要高速查找的不少地方,在Python代碼中幾乎無處不在,正確使用dict很是重要,須要牢記的第一條就是dict的key必須是不可變對象。這是由於dict根據key來計算value的存儲位置,若是每次計算相同的key得出的結果不一樣,那dict內部就徹底混亂了。這個經過key計算位置的算法稱爲哈希算法(Hash)。

要保證hash的正確性,做爲key的對象就不能變。在Python中,字符串、整數等都是不可變的,所以,能夠放心地做爲key。而list是可變的,就不能做爲key

五、可變類型與不可變類型

       上面咱們講了,str是不變對象,而list是可變對象。

對於可變對象,好比list,對list進行操做,list內部的內容是會變化的,好比:

>>> a = ['c', 'b', 'a']

>>> a.sort()

>>> a ['a', 'b', 'c']

而對於不可變對象,好比str,對str進行操做呢:

>>> a = 'abc'

>>> a.replace('a', 'A') 'Abc'

>>> a 'abc'

雖然字符串有個replace()方法,也確實變出了'Abc',但變量a最後還是'abc',應該怎麼理解呢?

咱們先把代碼改爲下面這樣:

>>> a = 'abc'

>>> b = a.replace('a', 'A')

>>> b 'Abc'>>> a 'abc'

要始終牢記的是,a是變量,而'abc'纔是字符串對象!有些時候,咱們常常說,對象a的內容是'abc',但實際上是指,a自己是一個變量,它指向的對象的內容纔是'abc':

 

當咱們調用a.replace('a', 'A')時,實際上調用方法replace是做用在字符串對象'abc'上的,而這個方法雖然名字叫replace,但卻沒有改變字符串'abc'的內容。相反,replace方法建立了一個新字符串'Abc'並返回,若是咱們用變量b指向該新字符串,就容易理解了,變量a仍指向原有的字符串'abc',但變量b卻指向新字符串'Abc'了:

 

因此,對於不變對象來講,調用對象自身的任意方法,也不會改變該對象自身的內容。相反,這些方法會建立新的對象並返回,這樣,就保證了不可變對象自己永遠是不可變的。

總結:

一、可變類型,值能夠改變:

列表 list

字典 dict

set  (沒有value的字典)

二、不可變類型,值不能夠改變:

數值類型 int, long, bool, float

字符串 str

元組 tuple

 

 

第五章Python的函數

一、函數介紹

       咱們知道圓的面積計算公式爲:S = πr2

 

當咱們知道半徑r的值時,就能夠根據公式計算出面積。假設咱們須要計算3個不一樣大小的圓的面積:

r1 = 12.34 r2 = 9.08 r3 = 73.1

s1 = 3.14 * r1 * r1

s2 = 3.14 * r2 * r2

s3 = 3.14 * r3 * r3

當代碼出現有規律的重複的時候,你就須要小心了,每次寫3.14 * x * x不只很麻煩,並且,若是要把3.14改爲3.14159265359的時候,得所有替換。

有了函數,咱們就再也不每次寫s = 3.14 * x * x,而是寫成更有意義的函數調用s = area_of_circle(x),而函數area_of_circle自己只須要寫一次,就能夠屢次調用。

基本上全部的高級語言都支持函數,Python也不例外。Python不但能很是靈活地定義函數,並且自己內置了不少有用的函數,能夠直接調用。

二、函數的定義與調用

       1、定義函數

定義函數的格式以下:

def 函數名(): 代碼

demo:

# 定義一個函數,可以完成打印信息的功能

def printInfo():

print'------------------------------------'

print' 人生苦短,我用Python'

print'------------------------------------'

2、調用函數

定義了函數以後,就至關於有了一個具備某些功能的代碼,想要讓這些代碼可以執行,須要調用它

調用函數很簡單的,經過 函數名() 便可完成調用

demo:

# 定義完函數後,函數是不會自動執行的,須要調用它才能夠

printInfo()

 

三、函數參數(一)

       思考一個問題,以下:

如今須要定義一個函數,這個函數可以完成2個數的加法運算,而且把結果打印出來,該怎樣設計?下面的代碼能夠嗎?有什麼缺陷嗎?

def add_2num():

a = 11

b = 22

c = a+b

print c

爲了讓一個函數更通用,即想讓它計算哪兩個數的和,就讓它計算哪兩個數的和,在定義函數的時候可讓函數接收數據,就解決了這個問題,這就是 函數的參數

<1> 定義帶有參數的函數

示例以下:

def add2num(a, b):

c = a+b

print c

<2> 調用帶有參數的函數

以調用上面的add2num(a, b)函數爲例:

def add2num(a, b):

c = a+b

print c

add2num(11, 22) #調用帶有參數的函數時,須要在小括號中,傳遞數據

<3> 練一練

要求:定義一個函數,完成前2個數完成加法運算,而後對第3個數,進行減法;而後調用這個函數

使用def定義函數,要注意有3個參數

調用的時候,這個函數定義時有幾個參數,那麼就須要傳遞幾個參數

<4> 小總結

定義時小括號中的參數,用來接收參數用的,稱爲 「形參」

調用時小括號中的參數,用來傳遞給函數用的,稱爲 「實參」

四、函數參數(二)

       1. 缺省參數

調用函數時,缺省參數的值若是沒有傳入,則被認爲是默認值。下例會打印默認的age,若是age沒有被傳入:

def printinfo( name, age = 35 ):# 打印任何傳入的字符串

print"Name: ", name

print"Age ", age # 調用printinfo函數

printinfo(name="miki" )

printinfo( age=9,name="miki" )

以上實例輸出結果:

Name: miki Age 35

Name: miki Age 9

注意:帶有默認值的參數必定要位於參數列表的最後面。

>>> defprintinfo(name, age=35, sex):

... print name

...

File "<stdin>", line 1 SyntaxError: non-default argument follows default argument

2.不定長參數

有時可能須要一個函數能處理比當初聲明時更多的參數。這些參數叫作不定長參數,聲明時不會命名。

基本語法以下:

Def functionname([formal_args,] *args, **kwargs):"函數_文檔字符串"

function_suite

return [expression]

加了星號(*)的變量args會存放全部未命名的變量參數,args爲元組;而加**的變量kwargs會存放命名參數,即形如key=value的參數, kwargs爲字典。

>>> def fun(a, b, *args, **kwargs):

... """可變參數演示示例"""

... print"a =", a

... print"b =", b

... print"args =", args

... print"kwargs: "

... for key, value in kwargs.items():

... print key, "=", value

...

>>> fun(1, 2, 3, 4, 5, m=6, n=7, p=8) # 注意傳遞的參數對應

a = 1

b = 2

args = (3, 4, 5)

kwargs: p = 8 m = 6 n = 7

>>>

>>> c = (3, 4, 5)

>>> d = {"m":6, "n":7, "p":8}

>>> fun(1, 2, *c, **d) # 注意元組與字典的傳參方式

a = 1

b = 2

args = (3, 4, 5)

kwargs: p = 8 m = 6 n = 7

>>> 

>>> fun(1, 2, c, d) # 注意不加星號與上面的區別

a = 1

b = 2

args = ((3, 4, 5), {'p': 8, 'm': 6, 'n': 7})

kwargs:

3. 引用傳參

可變類型與不可變類型的變量分別做爲函數參數時,會有什麼不一樣嗎?

Python有沒有相似C語言中的指針傳參呢?

>>> def selfAdd(a):... """自增"""... a += a

...

>>> a_int = 1

>>> a_int 1

>>> selfAdd(a_int)

>>> a_int 1

>>> a_list = [1, 2]

>>> a_list [1, 2]

>>> selfAdd(a_list)

>>> a_list [1, 2, 1, 2]

Python中函數參數是引用傳遞(注意不是值傳遞)。對於不可變類型,因變量不能修改,因此運算不會影響到變量自身;而對於可變類型來講,函數體中的運算有可能會更改傳入的參數變量。

五、函數返回值(一)

       <1>帶有返回值的函數

想要在函數中把結果返回給調用者,須要在函數中使用return

以下示例:

def add2num(a, b):

c = a+b

return c

或者

def add2num(a, b):

return a+b

<2>保存函數的返回值

在本小節剛開始的時候,說過的「買菸」的例子中,最後兒子給你煙時,你必定是從兒子手中接過來 對麼,程序也是如此,若是一個函數返回了一個數據,那麼想要用這個數據,那麼就須要保存

保存函數的返回值示例以下:

      

#定義函數

def add2num(a, b):

return a+b #調用函數,順便保存函數的返回值

result = add2num(100,98) #由於result已經保存了add2num的返回值,因此接下來就能夠使用了

print result

六、函數的返回值(二)

       在python中咱們可不能夠返回多個值?

>>> def divid(a, b):

... shang = a//b

... yushu = a%b

... return shang, yushu

...

>>> sh, yu = divid(5, 2)

>>> sh 5

>>> yu 1

本質是利用了元組

七、局部變量和全局變量

       一、局部變量

局部變量(Local variables)指在程序中只在特定過程或函數中能夠訪問的變量。

 

 

總結

一、局部變量,就是在函數內部定義的變量

二、不一樣的函數,能夠定義相同的名字的局部變量,可是各用個的不會產生影響

三、局部變量的做用,爲了臨時保存數據須要在函數中定義變量來進行存儲,這就是它的做用

二、全局變量

<1>什麼是全局變量

若是一個變量,既能在一個函數中使用,也能在其餘的函數中使用,這樣的變量就是全局變量

 

<2>全局變量和局部變量名字相同問題

<3>修改全局變量

既然全局變量,就是可以在因此的函數中進行使用,那麼能否進行修改呢?:global

<4>可變類型的全局變量

>>> a = 1

>>> deff():

... a += 1

... print a

...

>>> f()

Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f UnboundLocalError: local variable 'a' referenced before assignment

>>> li = [1,]

>>> deff2():

... li.append(1)

... print li

...

>>> f2() [1, 1]

>>> li [1, 1]

<5>總結1:

在函數外邊定義的變量叫作全局變量

全局變量可以在全部的函數中進行訪問

若是在函數中修改全局變量,那麼就須要使用global進行聲明,不然出錯

若是全局變量的名字和局部變量的名字相同,那麼使用的是局部變量的,小技巧:強龍不壓地頭蛇

<5>總結2:

在函數中不使用global聲明全局變量時不能修改全局變量的本質是不能修改全局變量的指向,即不能將全局變量指向新的數據。

對於不可變類型的全局變量來講,因其指向的數據不能修改,因此不使用global時沒法修改全局變量。

對於可變類型的全局變量來講,因其指向的數據能夠修改,因此不使用global時也可修改全局變量。

可變類型:值能夠修改(內存地址不變可是所保存的值變化了),引用能夠修改(變量的內存地址變化了)

不可變類型:值不能夠修改,能夠修改變量的引用(=賦值號)。

 

在函數裏面修改全局變量:

     一、若是全局變量是可變類型:因此在函數裏面任意修改(值,引用)

     二、若是全局變量是不可變類型:在函數裏面不能修改值,也不能修改引用,除非加上global才能修改引用。

八、遞歸函數

       <1>什麼是遞歸函數

經過前面的學習知道一個函數能夠調用其餘函數。

在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身自己,這個函數就是遞歸函數。

<2>遞歸函數的做用

舉個例子,咱們來計算階乘 n! = 1 * 2 * 3 * ... * n

解決辦法1:

 

看階乘的規律

1! = 1 2! = 2 × 1 = 2 × 1! 3! = 3 × 2 × 1 = 3 × 2! 4! = 4 × 3 × 2 × 1 = 4 × 3! ... n! = n × (n-1)!

解決辦法2:

 

遞歸函數案例:

    斐波拉契數列,該數列中有n個數字。

1 1 2 3 5 8

該數列中,從第三個數字開始:數值 =前一個數字 + 前前面一個數字

(n-1) + (n-2)

九、匿名函數

       一、匿名函數

用lambda關鍵詞能建立小型匿名函數。這種函數得名於省略了用def聲明函數的標準步驟。

lambda函數的語法只包含一個語句,以下:

lambda [arg1 [,arg2,.....argn]]:

expression

以下實例:

sum = lambda arg1, arg2: arg1 + arg2 #調用sum函數

print"Value of total : ", sum( 10, 20 )

print"Value of total : ", sum( 20, 20 )

以上實例輸出結果:

Value of total : 30

Value of total : 40

Lambda函數能接收任何數量的參數但只能返回一個表達式的值

匿名函數不能直接調用print,由於lambda須要一個表達式

二、應用場合

函數做爲參數傳遞

一、本身定義函數

>>> def fun(a, b, opt):

... print"a =", a

... print"b =", b

... print"result =", opt(a, b)

...

>>> fun(1, 2, lambda x,y:x+y)

a = 1

b = 2

result = 3

 

二、做爲內置函數的參數

想想,下面的數據如何指定按age或name排序?

stus = [ {"name":"zhangsan", "age":18}, {"name":"lisi", "age":19}, {"name":"wangwu", "age":17} ]

按name排序:

>>> stus.sort(key = lambda x:x['name'])

>>> stus [{'age': 19, 'name': 'lisi'}, {'age': 17, 'name': 'wangwu'}, {'age': 18, 'name': 'zhangsan'}]

 

按age排序:

>>> stus.sort(key = lambda x:x['age'])

>>> stus [{'age': 17, 'name': 'wangwu'}, {'age': 18, 'name': 'zhangsan'}, {'age': 19, 'name': 'lisi'}]

 

第六章Python的文件操做

一、文件的打開與關閉

       想想:若是想用word編寫一份簡歷,應該有哪些流程呢?

一、打開word軟件,新建一個word文件

二、寫入我的簡歷信息

三、保存文件

四、關閉word軟件

一樣,在操做文件的總體過程與使用word編寫一份簡歷的過程是很類似的 (io操做)

一、打開文件,或者新創建一個文件

二、讀/寫數據

三、關閉文件

<1>打開文件

在python,使用open函數,能夠打開一個已經存在的文件,或者建立一個新文件

open(文件名,訪問模式)

示例以下:

f = open(r'd:\nata\test.txt', 'w')

說明:

訪問模式

說明

r

以只讀方式打開文件。文件的指針將會放在文件的開頭。這是默認模式。

w

打開一個文件只用於寫入。若是該文件已存在則將其覆蓋。若是該文件不存在,建立新文件。

a

打開一個文件用於追加。若是該文件已存在,文件指針將會放在文件的結尾。也就是說,新的內容將會被寫入到已有內容以後。若是該文件不存在,建立新文件進行寫入。

rb

以二進制格式打開一個文件用於只讀。文件指針將會放在文件的開頭。這是默認模式。

wb

以二進制格式打開一個文件只用於寫入。若是該文件已存在則將其覆蓋。若是該文件不存在,建立新文件。

ab

以二進制格式打開一個文件用於追加。若是該文件已存在,文件指針將會放在文件的結尾。也就是說,新的內容將會被寫入到已有內容以後。若是該文件不存在,建立新文件進行寫入。

r+

打開一個文件用於讀寫。文件指針將會放在文件的開頭。

w+

打開一個文件用於讀寫。若是該文件已存在則將其覆蓋。若是該文件不存在,建立新文件。

a+

打開一個文件用於讀寫。若是該文件已存在,文件指針將會放在文件的結尾。文件打開時會是追加模式。若是該文件不存在,建立新文件用於讀寫。

rb+

以二進制格式打開一個文件用於讀寫。文件指針將會放在文件的開頭。

wb+

以二進制格式打開一個文件用於讀寫。若是該文件已存在則將其覆蓋。若是該文件不存在,建立新文件。

ab+

以二進制格式打開一個文件用於追加。若是該文件已存在,文件指針將會放在文件的結尾。若是該文件不存在,建立新文件用於讀寫。

<2>關閉文件

close( )

示例以下:

# 新建一個文件,文件名爲:

test.txt f = open('test.txt', 'w') # 關閉這個文件

f.close()

二、文件的讀寫

       <1>寫數據(write)

使用write()能夠完成向文件寫入數據

demo:

f = open('test.txt', 'w') f.write('hello world, i am here!') f.close()

注意:若是文件不存在那麼建立,若是存在那麼就先清空,而後寫入數據

<2>讀數據(read)

使用read(num)能夠從文件中讀取數據,num表示要從文件中讀取的數據的長度(單位是字節),若是沒有傳入num,那麼就表示讀取文件中全部的數據

demo:

f = open('test.txt', 'r')

content = f.read(1024)

print(content)

print("-"*30)

content = f.read()

print(content)

f.close()

注意:若是open是打開一個文件,那麼能夠不用謝打開的模式,即只寫 open('test.txt'),若是使用讀了屢次,那麼後面讀取的數據是從上次讀完後的位置開始的

<3>讀數據(readlines)

就像read沒有參數時同樣,readlines能夠按照行的方式把整個文件中的內容進行一次性讀取,而且返回的是一個列表,其中每一行的數據爲一個元素

#coding=utf-8

f = open('test.txt', 'r')

content = f.readlines()

print(type(content))

i=1

for temp in content:

print("%d:%s"%(i, temp))

i+=1

f.close()

 

<4>讀數據(readline)

#coding=utf-8

f = open('test.txt', 'r')

content = f.readline()

print("1:%s"%content)

content = f.readline()

print("2:%s"%content)

f.close()

三、文件的定位讀寫

<1>獲取當前讀寫的位置tell

在讀寫文件的過程當中,若是想知道當前的位置,能夠使用tell()來獲取

# 打開一個已經存在的文件

f = open("test.txt", "r")

str = f.read(3)

print"讀取的數據是 : ", str

# 查找當前位置

position = f.tell()

print"當前文件位置 : ", position

str = f.read(3)

print"讀取的數據是 : ", str

# 查找當前位置

position = f.tell()

print"當前文件位置 : ", position

f.close()

<2>定位到某個位置

若是在讀寫文件的過程當中,須要從另一個位置進行操做的話,能夠使用seek()

seek(offset, from)有2個參數

offset:偏移量

from:方向

0:表示文件開頭

1:表示當前位置

2:表示文件末尾

demo:把位置設置爲:從文件開頭,偏移5個字節

# 打開一個已經存在的文件

f = open("test.txt", "r")

str = f.read(30)

print"讀取的數據是 : ", str

# 查找當前位置

position = f.tell()

print"當前文件位置 : ", position

# 從新設置位置

f.seek(5,0)

# 查找當前位置

position = f.tell()

print"當前文件位置 : ", position

f.close()

demo:把位置設置爲:離文件末尾,3字節處

# 打開一個已經存在的文件

f = open("test.txt", "r")

# 查找當前位置

position = f.tell()

print"當前文件位置 : ", position

# 從新設置位置

f.seek(-3,2)

# 讀取到的數據爲:文件最後3個字節數據

str = f.read()

print"讀取的數據是 : ",

str f.close()

`四、文件的相關操做

       有些時候,須要對文件進行重命名、刪除等操做,python的os模塊中都有這麼功能

import os

python編程時,常常和文件、目錄打交道,這是就離不了os模塊。os模塊包含廣泛的操做系統功能,與具體的平臺無關。如下列舉經常使用的命令

1. os.name()——判斷如今正在實用的平臺,Windows 返回 ‘nt'; Linux 返回’posix'

    rename(須要修改的文件名, 新的文件名) 也能夠作剪切。

2. os.getcwd()——獲得當前工做的目錄。

3. os.listdir()——指定全部目錄下全部的文件和目錄名。

      

  以列表的形式所有列舉出來,其中沒有區分目錄和文件。

4. os.remove()——刪除指定文件

5. os.rmdir()——刪除指定目錄 :該目錄不能爲空

6. os.mkdir()——建立目錄

注意:這樣只能創建一層,要想遞歸創建可用:os.makedirs(x/y/z)

7. os.path.isfile()——判斷指定對象是否爲文件。是返回True,不然False

8. os.path.isdir()——判斷指定對象是否爲目錄。是True,不然False。例:         

9. os.path.exists()——檢驗指定的對象是否存在。是True,不然False.例:

10. os.path.split()——返回路徑的目錄和文件名。例:

 

此處只是把先後兩部分分開而已。就是找最後一個'/'。看例子:

 

11. os.getcwd()——得到當前工做的目錄(get current work dir)

12. os.system()——執行shell命令。例:   

 

注意:此處運行shell命令時,若是要調用python以前的變量,能夠用以下方式:

var=123

os.environ['var']=str(var) //注意此處[]內得是 「字符串」

os.system('echo $var')

13. os.chdir()——改變目錄到指定目錄

14. os.path.getsize()——得到文件的大小,若是爲目錄,返回0

15. os.path.abspath()——得到絕對路徑。例:

16. os.path.join(path, name)——鏈接目錄和文件名。例:

17.os.path.basename(path)——返回文件名

18. os.path.dirname(path)——返回文件所在目錄

第七章 類和對象

一、面向對象編程介紹

面向對象編程——Object Oriented Programming,簡稱OOP,是一種程序設計思想。OOP把對象做爲程序的基本單元,一個對象包含了數據和操做數據的函數。面向對象是一種對現實世界理解和抽象的方法。

「面向過程」(Procedure Oriented)是一種以過程爲中心的編程思想。「面向過程」也可稱之爲「面向記錄」編程思想,他們不支持豐富的「面向對象」特性(好比繼承、多態、封裝),而且它們不容許混合持久化狀態和域邏輯。

就是分析出解決問題所須要的步驟,而後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就能夠了。

面向過程是一件事「該怎麼作「,面向對象是一件事「該讓誰來作」,而後那個「誰」就是對象,他要怎麼作是他本身的事,反正最後一羣對象協力能把事作好就好了。

面向對象三個特性:繼承,封裝,多態。

二、類和對象

面向對象編程的2個很是重要的概念:類和對象

對象是面向對象編程的核心,在使用對象的過程當中,爲了將具備共同特徵和行爲的一組對象抽象定義,提出了另一個新的概念——類

類就至關於製造飛機時的圖紙,用它來進行建立的飛機就至關於對象

1. 類

人以類聚 物以羣分。 具備類似內部狀態和運動規律的實體的集合(或統稱爲抽象)。 具備相同屬性和行爲事物的統稱

類是抽象的,在使用的時候一般會找到這個類的一個具體的存在,使用這個具體的存在。一個類能夠找到多個對象

                    

2. 對象

某一個具體事物的存在 ,在現實世界中能夠是看得見摸得着的。 能夠是直接使用的

                    

       3. 類和對象之間的關係

 

小總結:類就是建立對象的模板

4. 練習:區分類和對象

奔馳汽車 類

奔馳smart 類

張三的那輛奔馳smart 對象

狗 類

大黃狗 類

李四家那隻大黃狗 對象

水果 類

蘋果 類

紅蘋果 類

紅富士蘋果 類

我嘴裏吃了一半的蘋果 對象

5. 類的構成

類(Class) 由3個部分構成

類的名稱:類名

類的屬性:一組數據

類的方法:容許對進行操做的方法 (行爲)

<1> 舉例:

1)人類設計,只關心3樣東西:

事物名稱(類名):人(Person)

屬性:身高(height)、年齡(age)

方法(行爲/功能):跑(run)、打架(fight)

2)狗類的設計

類名:狗(Dog)

屬性:品種 、毛色、性別、名字、 腿兒的數量

方法(行爲/功能):叫 、跑、咬人、吃、搖尾巴

三、定義類與建立對象

一、類的定義     

定義一個類,格式以下:

class 類名: 方法列表

demo:定義一個Car類

# 定義類

classCar:

# 方法

def getCarInfo(self):

print('車輪子個數:%d, 顏色%s'%(self.wheelNum, self.color))

def move(self):

print("車正在移動...")

說明:

一、定義類時有2種:新式類和經典類,上面的Car爲經典類,若是是Car(object)則爲新式類

二、類名的命名規則按照"大駝峯"

 

二、建立對象

經過上一節課程,定義了一個Car類;就比如有車一個張圖紙,那麼接下來就應該把圖紙交給生成工人們去生成了。

python中,能夠根據已經定義的類去建立出一個個對象

建立對象的格式爲:

對象名 = 類名()

建立對象demo:

# 定義類

class Car:

# 移動

def move(self):

print('車在奔跑...')

# 鳴笛

def toot(self):#self能夠不寫self,方法中必須有且一個參數。第一個參數表示當前對象。名字隨便取,可是習慣都寫self

print("車在鳴笛...嘟嘟..")

# 建立一個對象,並用變量BMW來保存它的引用

BMW = Car()

BMW.color = '黑色'

BMW.wheelNum = 4#輪子數量

BMW.move()

BMW.toot()

print(BMW.color)

print(BMW.wheelNum)

 

總結:

一、BMW = Car(),這樣就產生了一個Car的實例對象,必定在內存中有一塊空間存放對象的數據信息。此時也能夠經過實例對象BMW來訪問屬性或者方法

二、第一次使用BMW.color = '黑色'表示給BMW這個對象添加屬性,若是後面再次出現BMW.color = xxx表示對屬性進行修改

三、BMW是一個對象,它擁有屬性(數據)和方法(函數)

四、當建立一個對象時,就是用一個模子,來製造一個實物 

 

四、self

       1. 理解self

看以下示例:

# 定義一個類

class Animal:

# 方法

def __init__(self, name):

self.name = name

def printName(self):

print('名字爲:%s'%self.name)

# 定義一個函數

def myPrint(animal):

animal.printName()

dog1 = Animal('西西')

myPrint(dog1)

dog2 = Animal('北北')

myPrint(dog2)

總結

一、所謂的self,能夠理解爲本身

二、能夠把self當作C++中類裏面的this指針同樣理解,就是對象自身的意思

三、某個對象調用其方法時,python解釋器會把這個對象做爲第一個參數傳遞給self,因此開發者只須要傳遞後面的參數便可

二、__init__()方法

想想:

在上一小節的demo中,咱們已經給BMW這個對象添加了2個屬性,wheelNum(車的輪胎數量)以及color(車的顏色),試想若是再次建立一個對象的話,確定也須要進行添加屬性,顯然這樣作很費事,那麼有沒有辦法可以在建立對象的時候,就順便把車這個對象的屬性給設置呢?

 

<1>使用方式

def 類名:

#初始化函數,用來完成一些默認的設定

def__init__():pass

<2>__init__()方法的調用

# 定義汽車類

classCar:

def__init__(self):

self.wheelNum = 4

self.color = '藍色'

defmove(self):

print('車在跑,目標:夏威夷')

# 建立對象

BMW = Car()

print('車的顏色爲:%s'%BMW.color)

print('車輪胎數量爲:%d'%BMW.wheelNum)

 

總結1

當建立Car對象後,在沒有調用__init__()方法的前提下,BMW就默認擁有了2個屬性wheelNum和color,緣由是__init__()方法是在建立對象後,就馬上被默認調用了

想想:

既然在建立完對象後__init__()方法已經被默認的執行了,那麼可否讓對象在調用__init__()方法的時候傳遞一些參數呢?若是能夠,那怎樣傳遞呢?

# 定義汽車類

classCar:

def__init__(self, newWheelNum, newColor):

self.wheelNum = newWheelNum

self.color = newColor

def move(self):

print('車在跑,目標:夏威夷')

# 建立對象

BMW = Car(4, 'green')

print('車的顏色爲:%s'%BMW.color)

print('車輪子數量爲:%d'%BMW.wheelNum)

 

總結2

一、__init__()方法,在建立一個對象時默認被調用,不須要手動調用

二、__init__(self)中,默認有1個參數名字爲self,若是在建立對象時傳遞了2個實參,那麼__init__(self)中出了self做爲第一個形參外還須要2個形參,例如__init__(self,x,y)

三、__init__(self)中的self參數,不須要開發者傳遞,python解釋器會自動把當前的對象引用傳遞進去

       三、__new__方法

classA(object):

def__init__(self):

print("這是 init 方法")

def__new__(cls):

print("這是 new 方法")

return object.__new__(cls)

A()

總結

一、__new__至少要有一個參數cls,表明要實例化的類,此參數在實例化時由Python解釋器自動提供

二、__new__必需要有返回值,返回實例化出來的實例,這點在本身實現__new__時要特別注意,能夠return父類__new__出來的實例,或者直接是object的__new__出來的實例

三、__init__有一個參數self,就是這個__new__返回的實例,__init__在__new__的基礎上能夠完成一些其它初始化的動做,__init__不須要返回值

四、咱們能夠將類比做製造商,__new__方法就是前期的原材料購買環節,__init__方法就是在有原材料的基礎上,加工,初始化商品環節

注意點

 

特殊方法名

默認的參數

功能描述

__init__()

self

已經建立了對象,初始化對象回調方法

__str__()

self

和toString

__del__()

self

對象回收時候回調

__new__()

cls

對象建立的回調方法

 

       四、__del__()方法

建立對象後,python解釋器默認調用__init__()方法;

當刪除一個對象時,python解釋器也會默認調用一個方法,這個方法爲__del__()方法

當內存中構建一個對象數據的時候回調__init__()方法,

當內存中銷燬(釋放)一個對象時回調__del__()方法

import time

classAnimal(object):

# 初始化方法

# 建立完對象後會自動被調用

def__init__(self, name):

print('__init__方法被調用')

self.__name = name

# 析構方法

# 當對象被刪除時,會自動被調用

def__del__(self):

print("__del__方法被調用")

print("%s對象立刻被幹掉了..."%self.__name)

# 建立對象

dog = Animal("哈皮狗")

# 刪除對象

del dog

cat = Animal("波斯貓")

cat2 = cat

cat3 = cat

print("---立刻 刪除cat對象")

del cat

print("---立刻 刪除cat2對象")

del cat2

print("---立刻 刪除cat3對象")

del cat3

print("程序2秒鐘後結束")

time.sleep(2)

總結

一、當有1個變量保存了對象的引用時,此對象的引用計數就會加1

二、當使用del刪除變量指向的對象時,若是對象的引用計數不是1,好比3,那麼此時只會讓這個引用計數減1,即變爲2,當再次調用del時,變爲1,若是再調用1次del,此時會真的把對象進行刪除

五、"魔法"方法

1. 打印id()

若是把BMW使用print進行輸出的話,會看到以下的信息

 

即看到的是建立出來的BMW對象在內存中的地址

二、定義__str__()方法

classCar:

def__init__(self, newWheelNum, newColor):

self.wheelNum = newWheelNum

self.color = newColor

def__str__(self):

msg = "嘿,個人顏色是" + self.color + "我有" + str(self.wheelNum) + "個輪胎..."

return msg

def move(self):

print('車在跑,目標:夏威夷')

BMW = Car(4, "白色")

print(BMW)

總結

一、在python中方法名若是是__xxxx__()的,那麼就有特殊的功能,所以叫作「魔法」方法

二、當使用print輸出對象的時候,只要本身定義了__str__(self)方法,那麼就會打印從在這個方法中return的數據

五、保護對象的屬性

若是有一個對象,當須要對其進行修改屬性時,有2種方法

對象名.屬性名 = 數據 ---->直接修改

對象名.方法名() ---->間接修改

爲了更好的保存屬性安全,即不能隨意修改,通常的處理方式爲

將屬性定義爲私有屬性

添加一個能夠調用的方法,供調用

classPeople(object):

def__init__(self, name):

self.__name = name

defgetName(self):

return self.__name

defsetName(self, newName):

if len(newName) >= 5:

self.__name = newName

else:

print("error:名字長度須要大於或者等於5")

xiaoming = People("bin")

print(xiaoming.__name)

 

classPeople(object):

def__init__(self, name):

self.__name = name

defgetName(self):

return self.__name

defsetName(self, newName):

if len(newName) >= 5:

self.__name = newName

else:

print("error:名字長度須要大於或者等於5")

xiaoming = People("bin")

xiaoming.setName("wanger")

print(xiaoming.getName())

xiaoming.setName("lisi")

print(xiaoming.getName())

 

總結

一、Python中沒有像C++中public和private這些關鍵字來區別公有屬性和私有屬性

二、它是以屬性命名方式來區分,若是在屬性名前面加了2個下劃線'__',則代表該屬性是私有屬性,不然爲公有屬性(方法也是同樣,方法名前面加了2個下劃線的話表示該方法是私有的,不然爲公有的)。

六、繼承

       1. 繼承的概念

在現實生活中,繼承通常指的是子女繼承父輩的財產,以下圖

 

 

在程序中,繼承描述的是事物之間的所屬關係,例如貓和狗都屬於動物,程序中即可以描述爲貓和狗繼承自動物;同理,波斯貓和巴釐貓都繼承自貓,而沙皮狗和斑點狗都繼承足夠,以下如所示:

 

2. 繼承示例

# 定義一個父類,以下:

class Cat(object):

def __init__(self, name, color="白色"):

self.name = name

self.color = color

def run(self):

print("%s--在跑"%self.name)

# 定義一個子類,繼承Cat類,以下:

classBosi(Cat):

def setNewName(self, newName):

self.name = newName

def eat(self):

print("%s--在吃"%self.name)

bs = Bosi("印度貓")

print('bs的名字爲:%s'%bs.name)

print('bs的顏色爲:%s'%bs.color)

bs.eat()

bs.setNewName('波斯')

bs.run()

說明:

雖然子類沒有定義__init__方法,可是父類有,因此在子類繼承父類的時候這個方法就被繼承了,因此只要建立Bosi的對象,就默認執行了那個繼承過來的__init__方法

總結

一、子類在繼承的時候,在定義類時,小括號()中爲父類的名字

二、父類的屬性、方法,會被繼承給子類

3. 注意點

class Animal(object):

def __init__(self, name='動物', color='白色'):

self.__name = name

self.color = color

def __test(self):

print(self.__name)

print(self.color)

def test(self):

print(self.__name)

print(self.color)

class Dog(Animal):

def dogTest1(self):

#print(self.__name)

#不能訪問到父類的私有屬性

print(self.color)

def dogTest2(self):

#self.__test()

#不能訪問父類中的私有方法

self.test()

A = Animal()

#print(A.__name)

#程序出現異常,不能訪問私有屬性

print(A.color)

#A.__test()

#程序出現異常,不能訪問私有方法

A.test()

print("------分割線-----")

D = Dog(name = "小花狗", color = "黃色")

D.dogTest1()

D.dogTest2()

 

一、私有的屬性,不能經過對象直接訪問,可是能夠經過方法訪問

二、私有的方法,不能經過對象直接訪問

三、私有的屬性、方法,不會被子類繼承,也不能被訪問

四、通常狀況下,私有的屬性、方法都是不對外公佈的,每每用來作內部的事情,起到安全的做用

七、多繼承

1. 多繼承

 

從圖中可以看出,所謂多繼承,即子類有多個父類,而且具備它們的特徵

Python中多繼承的格式以下:

# 定義一個父類

classA:

def printA(self):

print('----A----')

# 定義一個父類

classB:

def printB(self):

print('----B----')

# 定義一個子類,繼承自A、B

class C(A,B):

def printC(self):

print('----C----')

obj_C = C()

obj_C.printA()

obj_C.printB()

運行結果:

----A----

----B----

說明:

一、python中是能夠多繼承的

二、父類中的方法、屬性,子類會繼承

注意點:

想想:

若是在上面的多繼承例子中,若是父類A和父類B中,有一個同名的方法,那麼經過子類去調用的時候,調用哪一個?

#coding=utf-8

class base(object):

def test(self):

print('----base test----')

classA(base):

def test(self):

print('----A test----')

# 定義一個父類

classB(base):

def test(self):

print('----B test----')

# 定義一個子類,繼承自A、B

classC(A,B):

pass

obj_C = C()

obj_C.test()

print(C.__mro__)

#能夠查看C類的對象搜索方法時的前後順序,C3算法獲得一個元組

       二、重寫

       <1>重寫父類方法

所謂重寫,就是子類中,有一個和父類相同名字的方法,在子類中的方法會覆蓋掉父類中同名的方法

#coding=utf-8

class Cat(object):

def sayHello(self):

print("halou-----1")

class Bosi(Cat):

def sayHello(self):

print("halou-----2")

bosi = Bosi() bosi.sayHello()

 

<2> 調用父類的方法

#coding=utf-8

class Cat(object):

def __init__(self,name):

self.name = name

self.color = 'yellow'

class Bosi(Cat):

def __init__(self,name):

# 調用父類的__init__方法1(python2)

#Cat.__init__(self,name)

# 調用父類的__init__方法2

#super(Bosi,self).__init__(name)

# 調用父類的__init__方法3

super().__init__(name)

def getName(self):

return self.name

bosi = Bosi('xiaohua')

print(bosi.name)

print(bosi.color)

八、多態

多態的概念是應用於Java和C#這一類強類型語言中,而Python崇尚「鴨子類型」。

所謂多態:定義時的類型和運行時的類型不同,此時就成爲多態

Python僞代碼實現Java或C#的多態

classF1(object):

def show(self):

print'F1.show'

classS1(F1):

def show(self):

print'S1.show'

classS2(F1):

defshow(self):

print'S2.show'

# 因爲在Java或C#中定義函數參數時,必須指定參數的類型# 爲了讓Func函數既能夠執行S1對象的show方法,又能夠執行S2對象的show方法,因此,定義了一個S1和S2類的父類# 而實際傳入的參數是:S1對象和S2對象

def Func(F1 obj):

"""Func函數須要接收一個F1類型或者F1子類的類型"""

print obj.show()

s1_obj = S1()

Func(s1_obj) # 在Func函數中傳入S1類的對象 s1_obj,執行 S1 的show方法,結果:S1.show

s2_obj = S2() Func(s2_obj)

 # 在Func函數中傳入Ss類的對象 ss_obj,執行 Ss 的show方法,結果:S2.show

Python 「鴨子類型」

class F1(object):

def show(self):

print'F1.show'

class S1(F1):

def show(self):

print'S1.show'

class S2(F1):

def show(self):

print'S2.show'

def Func(obj):

print obj.show()

s1_obj = S1()

Func(s1_obj)

s2_obj = S2()

Func(s2_obj)

九、類屬性與實例屬性

       在瞭解了類基本的東西以後,下面看一下python中這幾個概念的區別

先來談一下類屬性和實例屬性

在前面的例子中咱們接觸到的就是實例屬性(對象屬性),顧名思義,類屬性就是類對象所擁有的屬性,它被全部類對象的實例對象所共有,在內存中只存在一個副本,這個和C++,java中類的靜態成員變量有點相似。對於公有的類屬性,在類外能夠經過類對象和實例對象訪問。

 

類屬性:所屬類,這個類下全部的對象均可以共享這個類屬性。 至關於java中靜態屬性。

 

好比:

    Class   Person{

            public static  String  name="abc"

    }

一、類屬性

class People(object):

name = 'Tom'#公有的類屬性

__age = 12#私有的類屬性

p = People() print(p.name) #正確

print(People.name) #正確

print(p.__age) #錯誤,不能在類外經過實例對象訪問私有的類屬性

print(People.__age) #錯誤,不能在類外經過類對象訪問私有的類屬性

二、實例屬性(對象屬性)

classPeople(object):

address = '山東'#類屬性

def__init__(self):

self.name = 'xiaowang'#實例屬性

self.age = 20#實例屬性

p = People()

p.age =12#實例屬性

print(p.address) #正確

print(p.name) #正確

print(p.age) #正確

print(People.address) #正確

print(People.name) #錯誤

print(People.age) #錯誤

三、經過實例(對象)去修改類屬性

classPeople(object):

country = 'china'#類屬性

print(People.country)

p = People()

print(p.country)

p.country = 'japan'

print(p.country) #實例屬性會屏蔽掉同名的類屬性

print(People.country)

del p.country #刪除實例屬性

print(p.country)

 

總結

若是須要在類外修改類屬性,必須經過類對象去引用而後進行修改。若是經過實例對象去引用,會產生一個同名的實例屬性,這種方式修改的是實例屬性,不會影響到類屬性,而且以後若是經過實例對象去引用該名稱的屬性,實例屬性會強制屏蔽掉類屬性,即引用的是實例屬性,除非刪除了該實例屬性。

屬性叫法

變量叫法

描述

類屬性(私有和公有)

類變量

全部對象共享同一份類屬性。

實例屬性(私/公)

成員變量

每一個不一樣對象,有不同值的實例屬性

十、類方法和靜態方法

1. 類方法

是類對象所擁有的方法,須要用修飾器@classmethod來標識其爲類方法,對於類方法,第一個參數必須是類對象,通常以cls做爲第一個參數(固然能夠用其餘名稱的變量做爲其第一個參數,可是大部分人都習慣以'cls'做爲第一個參數的名字,就最好用'cls'了),可以經過實例對象和類對象去訪問。

classPeople(object):

country = 'china'#類方法,用classmethod來進行修飾  

@classmethod

def getCountry(cls):

return cls.country

p = People() print

p.getCountry() #能夠用過實例對象引用

print People.getCountry() #能夠經過類對象引用

類方法還有一個用途就是能夠對類屬性進行修改:

classPeople(object):

country = 'china'#類方法,用classmethod來進行修飾 @classmethod

def getCountry(cls):

return cls.country

@classmethod

Def setCountry(cls,country):

cls.country = country

p = People()

print p.getCountry() #能夠用過實例對象引用

print People.getCountry() #能夠經過類對象引用

p.setCountry('japan')

print p.getCountry()

print People.getCountry()

 

結果顯示在用類方法對類屬性修改以後,經過類對象和實例對象訪問都發生了改變

2. 靜態方法

須要經過修飾器@staticmethod來進行修飾,靜態方法不須要多定義參數

classPeople(object):

country = 'china'

@staticmethod#靜態方法

Def getCountry():

return People.country

print People.getCountry()

總結

從類方法和實例方法以及靜態方法的定義形式就能夠看出來,類方法的第一個參數是類對象cls,那麼經過cls引用的一定是類對象的屬性和方法;而實例方法的第一個參數是實例對象self,那麼經過self引用的多是類屬性、也有多是實例屬性(這個須要具體分析),不過在存在相同名稱的類屬性和實例屬性的狀況下,實例屬性優先級更高。靜態方法中不須要額外定義參數,所以在靜態方法中引用類屬性的話,必須經過類對象來引用

方法類別

語法

描述

類方法

@classmethod

第一個形參cls。默認傳遞

靜態方法

@staticmethod

沒有默認傳遞的形參

對象方法(成員方法)

def  方法名

第一個形參self ,默認傳遞

 

第八章設計模式

一、單例模式

       1. 單例是什麼

舉個常見的單例模式例子,咱們平常使用的電腦上都有一個回收站,在整個操做系統中,回收站只能有一個實例,整個系統都使用這個惟一的實例,並且回收站自行提供本身的實例。所以回收站是單例模式的應用。

確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例,這個類稱爲單例類,單例模式是一種對象建立型模式。

2. 建立單例-保證只有1個對象

# 實例化一個單例

classSingleton(object):

__instance = None

def__new__(cls, age, name):

#若是類數字可以__instance沒有或者沒有賦值

#那麼就建立一個對象,而且賦值爲這個對象的引用,保證下次調用這個方法時

#可以知道以前已經建立過對象了,這樣就保證了只有1個對象

If not cls.__instance:

cls.__instance = object.__new__(cls)

return cls.__instance

a = Singleton(18, "bin")

b = Singleton(8, "bin")

print(id(a))

print(id(b))

a.age = 19#給a指向的對象添加一個屬性

b.print(b.age)#獲取b指向的對象的age屬性

運行結果:

In [12]: class Singleton(object):

...: __instance = None

...:

...: def__new__(cls, age, name):

...: if not cls.__instance:

...: cls.__instance = object.__new__(cls)

...: return cls.__instance

...:

...: a = Singleton(18, "bin")

...: b = Singleton(8, "bin")

...:

...: print(id(a))

...: print(id(b))

...:

...: a.age = 19

...: print(b.age)

...: 4391023224439102322419

3. 建立單例時,只執行1次__init__方法

# 實例化一個單例

classSingleton(object):

__instance = None

__first_init = False

def__new__(cls, age, name):

if not cls.__instance:

cls.__instance = object.__new__(cls)

return cls.__instance

def__init__(self, age, name):

if not self.__first_init:

self.age = age

self.name = name

Singleton.__first_init = True

a = Singleton(18, "bin")

b = Singleton(8, "bin")

print(id(a))

print(id(b))

print(a.age)

print(b.age)

  1. age = 19
  2. print(b.age)

二、工廠模式

工廠模式是咱們最經常使用的實例化對象模式了,是用工廠方法代替new操做的一種模式。雖然這樣作,可能多作一些工做,但會給你係統帶來更大的可擴展性和儘可能少的修改量(可維護性)。

1. 簡單工廠模式

Simple Factory模式不是獨立的設計模式,他是Factory Method模式的一種簡單的、特殊的實現。他也被稱爲靜態工廠模式,一般建立者的建立方法被設計爲static方便調用。

一、靜態的工廠類

二、用全局函數改寫工廠類

 

 

 

 

2. 工廠方法模式

工廠方法模式去掉了簡單工廠模式中工廠方法的靜態方法,使得它能夠被子類繼承。對於python來講,就是工廠類被具體工廠繼承。這樣在簡單工廠模式裏集中在工廠方法上的壓力能夠由工廠方法模式裏不一樣的工廠子類來分擔。

抽象的工廠類提供了一個建立對象的方法,也叫做工廠方法。

1) 抽象工廠角色(Factory): 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。

2) 具體工廠角色(Stone_Axe_Factory,Steel_Axe_Factory):它含有和具體業務邏輯有關的代碼。由應用程序調用以建立對應的具體產品的對象。

3) 抽象產品角色(Axe):它是具體產品繼承的父類或者是實現的接口。在python中抽象產品通常爲父類。

4) 具體產品角色(Stone_Axe,Steel_Axe):具體工廠角色所建立的對象就是此角色的實例。由一個具體類實現。

第九章 異常

一、異常簡介

       看以下示例:

print'-----test--1---'

open('123.txt','r')

print'-----test--2---'

運行結果:

 

說明:

打開一個不存在的文件123.txt,當找不到123.txt 文件時,就會拋出給咱們一個IOError類型的錯誤,No such file or directory:123.txt (沒有123.txt這樣的文件或目錄)

異常:

當Python檢測到一個錯誤時,解釋器就沒法繼續執行了,反而出現了一些錯誤的提示,這就是所謂的"異常"

二、捕獲異常

       <1>捕獲異常 try...except...

看以下示例:

try:

print('-----test--1---')

open('123.txt','r')

print('-----test--2---')

except IOError:

pass

說明:

此程序看不到任何錯誤,由於用except 捕獲到了IOError異常,並添加了處理的方法

pass 表示實現了相應的實現,但什麼也不作;若是把pass改成print語句,那麼就會輸出其餘信息

小總結:

 

把可能出現問題的代碼,放在try中

把處理異常的代碼,放在except中

<2> except捕獲多個異常

看以下示例:

try:

print num

except IOError:

print('產生錯誤了')

想想:

上例程序,已經使用except來捕獲異常了,爲何還會看到錯誤的信息提示?

答:

except捕獲的錯誤類型是IOError,而此時程序產生的異常爲 NameError ,因此except沒有生效

修改後的代碼爲:

try:

print num

except NameError:

print('產生錯誤了')

實際開發中,捕獲多個異常的方式,以下:

#coding=utf-8

try:

print('-----test--1---')

open('123.txt','r') # 若是123.txt文件不存在,那麼會產生 IOError 異常 print('-----test--2---')

print(num)# 若是num變量沒有定義,那麼會產生 NameError 異常

except (IOError,NameError): #若是想經過一次except捕獲到多個異常能夠用一個元組的方式# errorMsg裏會保存捕獲到的錯誤信息

print(errorMsg)

 

注意:

當捕獲多個異常時,能夠把要捕獲的異常的名字,放到except 後,並使用元組的方式僅進行存儲

<3>獲取異常的信息描述

 

 

<4>捕獲全部異常

 

 

<5> else

我們應該對else並不陌生,在if中,它的做用是當條件不知足時執行的實行;一樣在try...except...中也是如此,即若是沒有捕獲到異常,那麼就執行else中的事情

try:

num = 100

print num

except NameError as errorMsg:

print('產生錯誤了:%s'%errorMsg)

else:

print('沒有捕獲到異常,真高興')

運行結果以下:

 

<6> try...finally...

try...finally...語句用來表達這樣的狀況:

在程序中,若是一個段代碼必需要執行,即不管異常是否產生都要執行,那麼此時就須要使用finally。 好比文件關閉,釋放鎖,把數據庫鏈接返還給鏈接池等

demo:

import time

try:

f = open('test.txt')

try:

whileTrue:

content = f.readline()

if len(content) == 0:

break

time.sleep(2)

print(content)

except TypeError as ex: === catch(NullPointException ex) #若是在讀取文件的過程當中,產生了異常,那麼就會捕獲到#好比 按下了 ctrl+c

pass

finally:

f.close()

print('關閉文件')

except:

print("沒有這個文件")

說明:

test.txt文件中每一行數據打印,可是我有意在每打印一行以前用time.sleep方法暫停2秒鐘。這樣作的緣由是讓程序運行得慢一些。在程序運行的時候,按Ctrl+c中斷(取消)程序。

咱們能夠觀察到KeyboardInterrupt異常被觸發,程序退出。可是在程序退出以前,finally從句仍然被執行,把文件關閉。

三、異常的傳遞

       1. try嵌套中

import time

try:

f = open('test.txt')

try:

while True:

content = f.readline()

if len(content) == 0:

break

time.sleep(2)

print(content)

finally:

f.close()

print('關閉文件')

except:

print("沒有這個文件")

運行結果:

In [26]: import time

...: try:

...: f = open('test.txt')

...: try:

...: while True:

...: content = f.readline()

...: if len(content) == 0:

...: break

...: time.sleep(2)

...: print(content)

...: finally:

...: f.close()

...: print('關閉文件')

...: except:

...: print("沒有這個文件")

...: finally:

...: print("最後的finally")

...: xxxxxxx--->這是test.txt文件中讀取到信息 ^C關閉文件 沒有這個文件 最後的finally

2. 函數嵌套調用中

def test1():

print("----test1-1----")

print(num)

print("----test1-2----")

def test2():

print("----test2-1----")

test1()

print("----test2-2----")

def test3():

try:

print("----test3-1----")

test1()

print("----test3-2----")

except Exception as result:

print("捕獲到了異常,信息是:%s"%result)

print("----test3-2----")

test3()

print("------華麗的分割線-----")

test2()

運行結果:

 

總結:

若是try嵌套,那麼若是裏面的try沒有捕獲到這個異常,那麼外面的try會接收到這個異常,而後進行處理,若是外邊的try依然沒有捕獲到,那麼再進行傳遞。。。

若是一個異常是在一個函數中產生的,例如函數A---->函數B---->函數C,而異常是在函數C中產生的,那麼若是函數C中沒有對這個異常進行處理,那麼這個異常會傳遞到函數B中,若是函數B有異常處理那麼就會按照函數B的處理方式進行執行;若是函數B也沒有異常處理,那麼這個異常會繼續傳遞,以此類推。。。若是全部的函數都沒有處理,那麼此時就會進行異常的默認處理,即一般見到的那樣

注意觀察上圖中,當調用test3函數時,在test1函數內部產生了異常,此異常被傳遞到test3函數中完成了異常處理,而當異常處理完後,並無返回到函數test1中進行執行,而是在函數test3中繼續執行

四、自定義異常

你能夠用raise語句來引起一個異常。異常/錯誤對象必須有一個名字,且它們應是Error或Exception類的子類

下面是一個引起異常的例子:

class ShortInputException(Exception):'''自定義的異常類'''

def__init__(self, length, atleast):

#super().__init__()

self.length = length

self.atleast = atleast

def main():

try:

s = input('請輸入 --> ')

if len(s) < 3: # raise引起一個你定義的異常

raise ShortInputException(len(s), 3)

except ShortInputException as result:#x這個變量被綁定到了錯誤的實例 print('ShortInputException: 輸入的長度是 %d,長度至少應是 %d'% (result.length, result.atleast))

else:

print('沒有異常發生.')

main()

注意

以上程序中,關於代碼#super().__init__()的說明

這一行代碼,能夠調用也能夠不調用,建議調用,由於__init__方法每每是用來對建立完的對象進行初始化工做,若是在子類中重寫了父類的__init__方法,即意味着父類中的不少初始化工做沒有作,這樣就不保證程序的穩定了,因此在之後的開發中,若是重寫了父類的__init__方法,最好是先調用父類的這個方法,而後再添加本身的功能

五、異常處理中拋出異常

classTest(object):

def __init__(self, switch):

self.switch = switch #開關

def calc(self, a, b):

try:

return a/b

except Exception as result:

if self.switch:

print("捕獲開啓,已經捕獲到了異常,信息以下:")

print(result)

else: #從新拋出這個異常,此時就不會被這個異常處理給捕獲到,從而觸發默認的異常處理

raise

a = Test(True)

a.calc(11,0)

print("----------------------華麗的分割線----------------")

a.switch = False

a.calc(11,0)

總結:

try:是異常捕獲開始代碼,try放在特別關心的那段代碼前面

    pass:若是這行代碼出現了異常,那麼後面的代碼不會運行

    pass2

    pass3

except 異常的類型 as ex: 捕獲某種類型的異常

except....多個except。按照順序依次比對類型

else:沒有異常時執行

finally:無論有沒有異常都會執行

第十章Python模塊及安裝

一、模塊的使用及安裝

       <1>Python中的模塊

在Python中有一個概念叫作模塊(module),這個和C語言中的頭文件以及Java中的jar包很相似,好比在Python中要調用sqrt函數,必須用import關鍵字引入math這個模塊,下面就來了解一下Python中的模塊。

說的通俗點:模塊就比如是工具包,要想使用這個工具包中的工具(就比如函數),就須要導入這個模塊

<2>import

在Python中用關鍵字import來引入某個模塊,好比要引用模塊math,就能夠在文件最開始的地方用import math來引入。

形如:

import module1,mudule2...

當解釋器遇到import語句,若是模塊在當前的搜索路徑就會被導入。

在調用math模塊中的函數時,必須這樣引用:

  模塊名.函數名

import math #這樣會報錯

print sqrt(2) #這樣才能正確輸出結果

print math.sqrt(2)

有時候咱們只須要用到模塊中的某個函數,只須要引入該函數便可,此時能夠用下面方法實現:

<3>from…import

Python的from語句讓你從模塊中導入一個指定的部分到當前命名空間中

語法以下:

from modname import name1[, name2[, ... nameN]]

例如,要導入模塊fib的fibonacci函數,使用以下語句:

from fib import fibonacci

注意:不會把整個fib模塊導入到當前的命名空間中,它只會將fib裏的fibonacci單個引入

<4>from … import *

把一個模塊的全部內容全都導入到當前的命名空間也是可行的,只需使用以下聲明:

from modname import *

注意:這提供了一個簡單的方法來導入一個模塊中的全部項目。然而這種聲明不應被過多地使用。

<5>定位模塊

當你導入一個模塊,Python解析器對模塊位置的搜索順序是:

一、當前目錄

二、若是不在當前目錄,Python則搜索在shell變量PYTHONPATH下的每一個目錄。

三、若是都找不到,Python會察看默認路徑。UNIX下,默認路徑通常爲/usr/local/lib/python/

四、模塊搜索路徑存儲在system模塊的sys.path變量中。變量裏包含當前目錄,PYTHONPATH和由安裝過程決定的默認目錄。

<6>安裝模塊

conda create -n py2 python=2.7

conda install 模塊

pip install 模塊

pymysql

numpy

二、模塊製做

<1>定義本身的模塊

在Python中,每一個Python文件均可以做爲一個模塊,模塊的名字就是文件的名字。

好比有這樣一個文件test.py,在test.py中定義了函數add

test.py

def add(a,b): return a+b

<2>調用本身定義的模塊

那麼在其餘文件中就能夠先import test,而後經過test.add(a,b)來調用了,固然也能夠經過from test import add來引入

main.py

import test result = test.add(11,22) print(result)

<3>測試模塊

在實際開中,當一個開發人員編寫完一個模塊後,爲了讓模塊可以在項目中達到想要的效果,這個開發人員會自行在py文件中添加一些測試信息,例如:

test.py

def add(a,b): return a+b # 用來進行測試 ret = add(12,22) print('int test.py file,,,,12+22=%d'%ret)

若是此時,在其餘py文件中引入了此文件的話,想一想看,測試的那段代碼是否也會執行呢!

main.py

import test result = test.add(11,22) print(result)

 

至此,可發現test.py中的測試代碼,應該是單獨執行test.py文件時才應該執行的,不該該是其餘的文件中引用而執行

爲了解決這個問題,python在執行一個文件時有個變量__name__

<4>模塊中的__all__

總結:

能夠根據__name__變量的結果可以判斷出,是直接執行的python腳本仍是被引入執行的,從而可以有選擇性的執行測試代碼

三、Python中的模塊

       一、python中的包

1. 引入包

1.1 包就是一個目錄

1.2 把多個py文件放到同一個文件夾下

1.3 使用import 文件夾.模塊 的方式導入

python3能夠導入包,python2不行。

1.4 使用from 文件夾 import 模塊 的方式導入

python3能夠導入包,python2不行。

1.5 在包的文件夾下建立__init__.py文件。

在python2中:有一個目錄,而且目錄下有一個__init__.py的文件。才叫包。

雖然文件內容沒有,可是python2能夠用了

 

有__init__.py文件在python3中沒有有錯。之後咱們都在包的目錄下新建一個init文件。

1.6 在__init__.py文件中寫入

from . import 模塊1

from . import 模塊2

那麼能夠使用import 文件夾 導入

1.7 也能夠使用from 文件夾 import 模塊 的方式導入

總結:

包將有聯繫的模塊組織在一塊兒,即放到同一個文件夾下,而且在這個文件夾建立一個名字爲__init__.py 文件,那麼這個文件夾就稱之爲包

有效避免模塊名稱衝突問題,讓應用組織結構更加清晰

2. __init__.py文件有什麼用

__init__.py 控制着包的導入行爲

2.1 __init__.py爲空

僅僅是把這個包導入,不會導入包中的模塊

2.2 (瞭解)能夠在__init__.py文件中編寫內容

能夠在這個文件中編寫語句,當導入時,這些語句就會被執行

__init__.py文件 

四、模塊的發佈

1.mymodule目錄結構體以下:

.

├── setup.py

├── suba

│   ├── aa.py

│   ├── bb.py

│   └── __init__.py

└── subb

├── cc.py

├── dd.py

└── __init__.py

2.編輯setup.py文件

py_modules需指明所需包含的py文件

from distutils.core import setup

setup(name="壓縮包的名字", version="1.0", description="描述", author="做者", py_modules=['suba.aa', 'suba.bb', 'subb.cc', 'subb.dd'])

3.構建模塊

python setup.py build

4.生成發佈壓縮包

python setup.py sdist

五、模塊安裝、使用

1.安裝的方式

一、找到模塊的壓縮包(拷貝到其餘地方)

二、解壓

三、進入文件夾

四、執行命令python setup.py install

注意:若是在install的時候,執行目錄安裝,能夠使用python setup.py install --prefix=安裝路徑

conda create -n py2 python=2.7

2.模塊的引入

在程序中,使用from import 便可完成對安裝的模塊使用

from 模塊名 import 模塊名或者*

第十一章 列表推導式

一、給程序傳參數

import sys print(sys.argv)

二、列表推導式

一、所謂的列表推導式,就是指的輕量級循環建立列表:

a = [i for i in range(1,10)]

b= [11 for i in range(1,10)]

[(1,1),(2,4),(3,9),(4,16).....]

二、在循環的過程當中使用if 來肯定 列表中元素的條件

a = [i for i in range(1,10) if i%2==0]

三、2個for循環

a=[(i,j) for i in range(1,5) for j in range(6,10)]

四、3個for循環

a= [(x,y,z) for x in range(2) for y in range(2) for z in range(2)]

 

三、set:集合類型

列表(list)

a=[]

前後順序,有下標位[index],能夠重複,可變類型

元組(tuple)

a=()

有前後順序,有下標位,元素能夠重複,不可變(只能查)

字典(dict)

a={key:value}

沒有前後順序,沒有下標,key不可重複,value能夠,可變

集合(set)

a=set()

沒有前後順序,沒有下標,不可重複,可變類型

 

注意:使用set,能夠快速的完成對list中的元素去重複的功能

相關文章
相關標籤/搜索