第3章 Python基礎
由於作者寫的這本書完全是以Python語言爲基礎的,所以需要讀者具備一定的Python編程能力。如果說最好的Python基礎教程,那應該說是《笨方法學Python》了。
3.1 Python哲學
<span style="color:#000000"><code>Python <span style="color:#006666">2.7</span><span style="color:#006666">.13</span> (v2<span style="color:#006666">.7</span><span style="color:#006666">.13</span>:a06454b1afa1, Dec <span style="color:#006666">17</span> <span style="color:#006666">2016</span>, <span style="color:#006666">20</span>:<span style="color:#006666">42</span>:<span style="color:#006666">59</span>) [MSC v<span style="color:#006666">.1500</span> <span style="color:#006666">32</span> bit (Intel)] <span style="color:#000088">on</span> win32
Type <span style="color:#009900">"copyright"</span>, <span style="color:#009900">"credits"</span> <span style="color:#000088">or</span> <span style="color:#009900">"license()"</span> <span style="color:#000088">for</span> more information.
>>> import this
The Zen <span style="color:#000088">of</span> Python, <span style="color:#000088">by</span> Tim Peters
Beautiful <span style="color:#000088">is</span> better than ugly.
Explicit <span style="color:#000088">is</span> better than implicit.
Simple <span style="color:#000088">is</span> better than complex.
Complex <span style="color:#000088">is</span> better than complicated.
Flat <span style="color:#000088">is</span> better than nested.
Sparse <span style="color:#000088">is</span> better than dense.
Readability counts.
Special cases aren't special enough <span style="color:#000088">to</span> break <span style="color:#000088">the</span> rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In <span style="color:#000088">the</span> face <span style="color:#000088">of</span> ambiguity, refuse <span style="color:#000088">the</span> temptation <span style="color:#000088">to</span> guess.
There should be one<span style="color:#880000">-- and preferably only one --obvious way to do it.</span>
Although <span style="color:#000088">that</span> way may <span style="color:#000088">not</span> be obvious <span style="color:#000088">at</span> <span style="color:#000088">first</span> unless you're Dutch.
Now <span style="color:#000088">is</span> better than never.
Although never <span style="color:#000088">is</span> often better than *right* now.
If <span style="color:#000088">the</span> implementation <span style="color:#000088">is</span> hard <span style="color:#000088">to</span> explain, <span style="color:#000088">it</span>'s a bad idea.
If <span style="color:#000088">the</span> implementation <span style="color:#000088">is</span> easy <span style="color:#000088">to</span> explain, <span style="color:#000088">it</span> may be a good idea.
Namespaces are one honking great idea <span style="color:#880000">-- let's do more of those!</span>
>>> </code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
翻譯爲中文就是:
- 優美勝於醜陋
- 明瞭勝於晦澀
- 簡單勝過複雜
- 扁平勝於嵌套
- 間隔勝於緊湊
- 可讀性很重要
- 即使假錯特例的實用性之名,也不違背這些規則
- 雖然實用性次於純度
- 錯誤不應該被無聲的忽略
- 除非明確的沉默
- 當存在多種可能時,不要嘗試去猜測
- 應該有一個,最好只有一個,很明顯可以做到這一點
- 雖然這種方式可能不容易,除非你是Python之父
- 現在做總比不做好
- 雖然過期從未比現在好
- 如果這個實現不容易解釋,那麼它肯定是壞主意
- 如果這個實現容易解釋,那麼它很可能是個好主意
- 命名空間是一種絕妙的理念,應當多加利用
3.2 輸出與輸入
3.2.1 print打印
Python提供print()方法來打印信息:
<span style="color:#000000"><code class="language-python">>>><span style="color:#000088">print</span> (<span style="color:#009900">"hello python"</span>)
hello python</code></span>
- 1
- 2
打印變量:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>name = <span style="color:#009900">"zhangsan"</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"hello %s , Nice to meet you!"</span> % name)
hello zhangsan , Nice to meet you!
<span style="color:#006666">>>> </span>name = <span style="color:#009900">"Lisi"</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"hello %s , Nice to meet you!"</span> % name)
hello Lisi , Nice to meet you!</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
%s 只能打印字符串,如果想要打印數組,需要使用%d:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>age = <span style="color:#006666">27</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"You are %d !"</span> % age)
You are <span style="color:#006666">27</span> !</code></span>
- 1
- 2
- 3
如果不知道自己打印的類型,可以使用%r:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>age = <span style="color:#006666">27</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"You are %d !"</span> % age)
You are <span style="color:#006666">27</span> !
<span style="color:#006666">>>> </span>
<span style="color:#006666">>>> </span>n =<span style="color:#006666">100</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"You print is %r ."</span> % n)
You <span style="color:#000088">print</span> <span style="color:#000088">is</span> <span style="color:#006666">100</span> .
<span style="color:#006666">>>> </span>n = <span style="color:#009900">"abc"</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"You print is %r ."</span> % n)
You <span style="color:#000088">print</span> <span style="color:#000088">is</span> <span style="color:#009900">'abc'</span> .
<span style="color:#006666">>>> </span>name = <span style="color:#009900">"zhangsan"</span>
<span style="color:#006666">>>> </span>age = <span style="color:#006666">22</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"student info: %s %d ."</span> % (name, age))
student info: zhangsan <span style="color:#006666">22</span> .</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
3.2.2 input輸入
如果希望打印的是程序運行過程中由用戶來決定的內容,可以使用input()方法:
<span style="color:#000000"><code class="language-python">n = input(<span style="color:#009900">"Enter any content: "</span>)
<span style="color:#000088">print</span> <span style="color:#009900">"Your input is %r"</span> % n</code></span>
- 1
- 2
運行上述腳本時,用戶輸入的信息就會被打印出來。
3.2.3 引號與註釋
Python不區分單引號、雙引號,都可以用來表示一個字符串:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"hello"</span>)
hello
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">'hello'</span>)
hello</code></span>
- 1
- 2
- 3
- 4
單引號和雙引號可以相互嵌套使用,但不能交叉使用:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"你說:'早上你好'"</span>)
你說:<span style="color:#009900">'早上你好'</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">'我說:"今天天氣不錯"'</span>)
我說:<span style="color:#009900">"今天天氣不錯"</span>
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> (<span style="color:#009900">"你微笑着'向我道別"</span>。<span style="color:#009900">')
SyntaxError: invalid syntax</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Python的單行註釋使用“#”表示:
<span style="color:#000000"><code class="language-python">>>><span style="color:#880000">#單行註釋</span>
>>><span style="color:#000088">print</span> (<span style="color:#009900">"hello world"</span>) <span style="color:#880000">#打印hello world</span>
hello world</code></span>
- 1
- 2
- 3
多行註釋使用三對引號表示,同樣不區分單、雙引號:
<span style="color:#000000"><code class="language-python"><span style="color:#009900">"""
我們實現一個偉大的程序
那麼是
print 一行數據 ^_^
"""</span>
<span style="color:#009900">'''
This is a
Multi line comment
'''</span>
<span style="color:#000088">print</span> (<span style="color:#009900">"Hello World"</span>)</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
3.3 分支與循環
結構化程序實質上是由有限個順序、分支和循環三種基本結構排列、嵌套而成。
3.3.1 if語句
if實現分支判斷,一般語法爲:if…else…
<span style="color:#000000"><code class="language-python">>>>a = <span style="color:#006666">2</span>
>>>b = <span style="color:#006666">3</span>
>>><span style="color:#000088">if</span> a > b:
<span style="color:#000088">print</span> (<span style="color:#009900">"a max!"</span>)
<span style="color:#000088">else</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"b max!"</span>)
b max!</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
注意: Python沒有像其他語言一樣使用“{}”表示語句體,而是通過語句的縮進來判斷語句體,縮進默認爲4個空格。
if語句通過“==”運算符判斷相等:
<span style="color:#000000"><code class="language-python">>>>student = <span style="color:#009900">"xiaoming"</span>
>>><span style="color:#000088">if</span> student == <span style="color:#009900">"xiaoming"</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"xiaoming, You are on duty today."</span>)
<span style="color:#000088">else</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"Please call xiaoming to duty"</span>)
xiaoming, You are on duty today.</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
if語句通過“!=”運算符判斷不相等;
if語句還可以使用“in”、“not in”表示包含關係:
<span style="color:#000000"><code class="language-python">>>>hi = <span style="color:#009900">"hello world"</span>
>>><span style="color:#000088">if</span> <span style="color:#009900">"hello"</span> <span style="color:#000088">in</span> hi:
<span style="color:#000088">print</span> (<span style="color:#009900">"Contain"</span>)
<span style="color:#000088">else</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"Not Contain"</span>)
Contain</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
if語句還可以進行布爾類型的判斷:
<span style="color:#000000"><code class="language-python">>>>a = <span style="color:#000088">True</span>
>>><span style="color:#000088">if</span> a:
<span style="color:#000088">print</span> (<span style="color:#009900">"a is True"</span>)
<span style="color:#000088">else</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"a is not True"</span>)
a <span style="color:#000088">is</span> <span style="color:#000088">True</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
練習:
<span style="color:#000000"><code class="language-python">results = <span style="color:#006666">72</span>
<span style="color:#000088">if</span> results >= <span style="color:#006666">90</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"優秀"</span>)
<span style="color:#000088">elif</span> results >= <span style="color:#006666">70</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"良好"</span>)
<span style="color:#000088">elif</span> results >= <span style="color:#006666">60</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"及格"</span>)
<span style="color:#000088">else</span>:
<span style="color:#000088">print</span> (<span style="color:#009900">"不及格"</span>)</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
答案:良好。
3.3.2 for語句
Python提供了兩種循環:while循環、for循環。
for循環的使用更加靈活、簡單,可以直接對一個字符串進行遍歷:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">for</span> i <span style="color:#000088">in</span> <span style="color:#009900">"hello world"</span>:
<span style="color:#000088">print</span> (i)
h
e
l
l
o
w
o
r
l
d</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
對一個字典進行遍歷:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>fruits = [<span style="color:#009900">'banana'</span>, <span style="color:#009900">'apple'</span>, <span style="color:#009900">'mango'</span>]
<span style="color:#006666">>>> </span><span style="color:#000088">for</span> fruit <span style="color:#000088">in</span> fruits:
<span style="color:#000088">print</span> fruit
banana
apple
mango</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
使用range()函數來進行指定次數的循環:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">for</span> i <span style="color:#000088">in</span> range(<span style="color:#006666">5</span>):
<span style="color:#000088">print</span> (i)
<span style="color:#006666">0</span>
<span style="color:#006666">1</span>
<span style="color:#006666">2</span>
<span style="color:#006666">3</span>
<span style="color:#006666">4</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
注意: range()函數默認從0開始循環。
指定起始位置和步長的循環:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">for</span> i <span style="color:#000088">in</span> range(<span style="color:#006666">1</span>, <span style="color:#006666">10</span>, <span style="color:#006666">2</span>):
<span style="color:#000088">print</span> (i)
<span style="color:#006666">1</span>
<span style="color:#006666">3</span>
<span style="color:#006666">5</span>
<span style="color:#006666">7</span>
<span style="color:#006666">9</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
range(start, end[, step])
start表示開始位置、end表示結束位置、step表示每一次循環的步長。
python2:range() 是一個生成器,xrange()是一個數組,功能完全一樣,性能後者優於前者;
python3:range()和xrange()相同,都是一個數組。
3.4 數組與字典
3.4.1 數組
數組:用方括號[]表示,裏面的每一項用逗號“,”分隔。
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>lists = [<span style="color:#006666">1</span>, <span style="color:#006666">2</span>, <span style="color:#006666">3</span>, <span style="color:#009900">'a'</span>, <span style="color:#006666">5</span>]
<span style="color:#006666">>>> </span>lists
[<span style="color:#006666">1</span>, <span style="color:#006666">2</span>, <span style="color:#006666">3</span>, <span style="color:#009900">'a'</span>, <span style="color:#006666">5</span>]
<span style="color:#006666">>>> </span>lists[<span style="color:#006666">0</span>]
<span style="color:#006666">1</span>
<span style="color:#006666">>>> </span>lists[<span style="color:#006666">4</span>]
<span style="color:#006666">5</span>
<span style="color:#006666">>>> </span>lists[<span style="color:#006666">4</span>] = <span style="color:#009900">'b'</span>
<span style="color:#006666">>>> </span>lists[<span style="color:#006666">4</span>]
<span style="color:#009900">'b'</span>
<span style="color:#006666">>>> </span>lists.append(<span style="color:#009900">'c'</span>)
<span style="color:#006666">>>> </span>lists
[<span style="color:#006666">1</span>, <span style="color:#006666">2</span>, <span style="color:#006666">3</span>, <span style="color:#009900">'a'</span>, <span style="color:#009900">'b'</span>, <span style="color:#009900">'c'</span>]</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
注意:
- Python允許在數組裏任意地防止數字或字符串
- 數組下標是從0開始
- append()函數可以向數組末尾追加新項
3.4.2 字典
字典:用花括號{}表示,裏面的項是成對出現,一個key對應一個value,key與value之間用冒號分隔,不同的項之間用逗號“,”分隔。
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>dicts = {<span style="color:#009900">"username"</span>:<span style="color:#009900">"zhangsan"</span>,<span style="color:#009900">'password'</span>:<span style="color:#006666">123456</span>}
<span style="color:#006666">>>> </span>dicts.keys()
[<span style="color:#009900">'username'</span>, <span style="color:#009900">'password'</span>]
<span style="color:#006666">>>> </span>dicts.values()
[<span style="color:#009900">'zhangsan'</span>, <span style="color:#006666">123456</span>]
<span style="color:#006666">>>> </span>dicts.items()
[(<span style="color:#009900">'username'</span>, <span style="color:#009900">'zhangsan'</span>), (<span style="color:#009900">'password'</span>, <span style="color:#006666">123456</span>)]
<span style="color:#006666">>>> </span><span style="color:#000088">for</span> k,v <span style="color:#000088">in</span> dicts.items():
<span style="color:#000088">print</span> (<span style="color:#009900">"dicts keys is %r"</span> % k)
<span style="color:#000088">print</span> (<span style="color:#009900">"dicts values is %r"</span> % v)
dicts keys <span style="color:#000088">is</span> <span style="color:#009900">'username'</span>
dicts values <span style="color:#000088">is</span> <span style="color:#009900">'zhangsan'</span>
dicts keys <span style="color:#000088">is</span> <span style="color:#009900">'password'</span>
dicts values <span style="color:#000088">is</span> <span style="color:#006666">123456</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
注意: Python規定一個字典中的key必須獨一無二,valuekey相同。
- keys()函數:返回字典key的列表
- values()函數:返回字典value的列表
- items()函數:將所有的字典項以列表方式返回
按存放的順序輸出字典:
<span style="color:#000000"><code class="language-python"><span style="color:#880000"># 通過zip方法合併兩個List爲Dictionary</span>
<span style="color:#880000"># 遍歷會按原先的順序</span>
keys = [<span style="color:#009900">"b"</span>, <span style="color:#009900">"a"</span>, <span style="color:#009900">"c"</span>, <span style="color:#009900">"e"</span>, <span style="color:#009900">"d"</span>]
values = [<span style="color:#009900">"2"</span>, <span style="color:#009900">"1"</span>, <span style="color:#009900">"3"</span>, <span style="color:#009900">"5"</span>, <span style="color:#009900">"4"</span>]
<span style="color:#000088">for</span> key,value <span style="color:#000088">in</span> zip(keys, values):
<span style="color:#000088">print</span> (key, value)</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
輸出結果:
b 2
a 1
c 3
e 5
d 4
3.5 函數、類和方法
3.5.1 函數
Python通過def關鍵字來定義函數:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(a, b)</span>:
<span style="color:#000088">print</span> (a + b)
<span style="color:#006666">>>> </span>add(<span style="color:#006666">3</span>, <span style="color:#006666">5</span>)
<span style="color:#006666">8</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
通常函數不會直接打印結果,而是將結果通過return關鍵字返回:
<span style="color:#000000"><code class="language-python">>>><span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(a, b)</span>:
<span style="color:#000088">return</span> a + b
>>>add(<span style="color:#006666">3</span>, <span style="color:#006666">5</span>)
<span style="color:#006666">8</span></code></span>
- 1
- 2
- 3
- 4
如果在調用函數時不想傳參,可以爲函數設置默認參數:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(a=<span style="color:#006666">1</span>, b=<span style="color:#006666">2</span>)</span>:
<span style="color:#000088">return</span> a + b
<span style="color:#006666">>>> </span>add()
<span style="color:#006666">3</span>
<span style="color:#006666">>>> </span>add(<span style="color:#006666">3</span>, <span style="color:#006666">5</span>)
<span style="color:#006666">8</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
3.5.2 類和方法
在面向對象編程的世界裏,一切皆爲對象,抽象的一組對象就是類。
eg:汽車是一個類,而張三家的奇瑞汽車就是一個具體的對象。
Python使用class關鍵字來創建類。
<span style="color:#000000"><code class="language-python"><span style="color:#000088">class</span> <span style="color:#4f4f4f">A</span><span style="color:#4f4f4f">(object)</span>:
<span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(self, a, b)</span>:
<span style="color:#000088">return</span> a + b
count = A()
<span style="color:#000088">print</span> (count.add(<span style="color:#006666">3</span>, <span style="color:#006666">5</span>))</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
輸出結果爲:8
對上述代碼分析:
- 創建一個類A(在Python 3中object爲所有類的基類,所有類在創建時默認繼承object,所以不聲明繼承object也可以)
- 在類下面創建一個add()方法,注意,方法的第一個參數必須是存在的,一般習慣命名爲self,但在調用這個方法時不需要爲這個參數傳值
一般在創建類時會首先聲明初始化方法__init__(),注意,init的兩側是雙下劃線,當我們在調用該類時,可以用來進行一下初始化工作:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">class</span> <span style="color:#4f4f4f">A</span><span style="color:#4f4f4f">(object)</span>:
<span style="color:#000088">def</span> <span style="color:#009900">__init__</span><span style="color:#4f4f4f">(self, a, b)</span>:
self.a = int(a)
self.b = int(b)
<span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(self)</span>:
<span style="color:#000088">return</span> self.a + self.b
count = A(<span style="color:#009900">'4'</span>, <span style="color:#006666">5</span>)
<span style="color:#000088">print</span> (count.add())</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
輸出結果爲:9
對上述代碼分析:
- 當調用A類時首先會執行它的__init__()方法,所以需要對其進行傳參
- 初始化的工作就是將輸入的參數類型轉化爲int類型,保證程序容錯性
- add()方法可以直接拿初始化方法的self.a和self.b兩個數進行計算
- 所以在調用A類下面的add()方法時,不需要再傳參
Python中類的繼承:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">class</span> <span style="color:#4f4f4f">A</span><span style="color:#4f4f4f">()</span>:
<span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(self, a, b)</span>:
<span style="color:#000088">return</span> a + b
<span style="color:#000088">class</span> <span style="color:#4f4f4f">B</span><span style="color:#4f4f4f">(A)</span>:
<span style="color:#000088">def</span> <span style="color:#009900">sub</span><span style="color:#4f4f4f">(self, a, b)</span>:
<span style="color:#000088">return</span> a - b
<span style="color:#000088">print</span> (B().add(<span style="color:#006666">4</span>, <span style="color:#006666">5</span>))</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
輸出結果爲:9
對上述代碼分析:
- 創建一個A類,在下面創建add()方法用於計算兩個參數相加
- 創建一個B類,繼承A類,並且又繼續創建sub()方法用於計算兩個參數相減
- 因爲B類繼承了A類,所以B類自然也擁有了add()方法,從而可以直接通過B類調用add()方法
3.6 模組
模組=類庫、模塊。
3.6.1 引用模塊
通過:import…或者from…import…的方式引用模塊,eg:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">import</span> time
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> time.ctime()
Mon Mar <span style="color:#006666">19</span> <span style="color:#006666">16</span>:<span style="color:#006666">20</span>:<span style="color:#006666">26</span> <span style="color:#006666">2018</span></code></span>
- 1
- 2
- 3
如果確定只需要使用time下面的ctime()方法,還可以這樣引用,eg:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">from</span> time <span style="color:#000088">import</span> ctime
<span style="color:#006666">>>> </span><span style="color:#000088">print</span> ctime()
Mon Mar <span style="color:#006666">19</span> <span style="color:#006666">16</span>:<span style="color:#006666">22</span>:<span style="color:#006666">00</span> <span style="color:#006666">2018</span></code></span>
- 1
- 2
- 3
現在使用時就不必告訴Python,ctime()方法是time模塊所提供的了。
但是實際情況,可能是我們還需要使用time模塊下的sleep()方法,我們也可以這樣引入進來,但是還有其他方法呢,所以我們可以一次性把time模塊下的所有方法都引入進來,eg:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> time <span style="color:#000088">import</span> *
<span style="color:#000088">print</span> ctime()
<span style="color:#000088">print</span> <span style="color:#009900">"休眠兩秒"</span>
sleep(<span style="color:#006666">2</span>)
<span style="color:#000088">print</span> ctime()</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
最終輸出結果是:
<span style="color:#000000"><code class="language-shell"><span style="color:#000000">Mon</span> <span style="color:#000000">Mar</span> 19 16<span style="color:#000000">:46</span><span style="color:#000000">:22</span> 2018
休眠兩秒
<span style="color:#000000">Mon</span> <span style="color:#000000">Mar</span> 19 16<span style="color:#000000">:46</span><span style="color:#000000">:24</span> 2018</code></span>
- 1
- 2
- 3
其中,星號(*),代表了模塊下的所有方法。通過導入模塊後,可以使用help查看模塊的doc,eg:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">import</span> time
help(time)</code></span>
- 1
- 2
pip所安裝的Python第三方庫或框架,都可以使用這種方式來查看。
3.6.2 模塊調用
一個軟件項目不可能把所有代碼都放在一個文件中實現,一般會按照一定規則在不同的目錄和文件中實現。
創建一個目錄project,並在目錄下創建兩個文件,結構如下:
<span style="color:#000000"><code><span style="color:#880000">project/</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">pub</span><span style="color:#009900">.</span><span style="color:#880000">py</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">count</span><span style="color:#009900">.</span><span style="color:#880000">py</span></code></span>
- 1
- 2
- 3
在pub.py文件中創建add函數:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(a, b)</span>:
<span style="color:#000088">return</span> a + b</code></span>
- 1
- 2
在count.py文件中調用pub.py文件中的add()函數:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> pub <span style="color:#000088">import</span> add
<span style="color:#000088">print</span> add(<span style="color:#006666">4</span>, <span style="color:#006666">5</span>)</code></span>
- 1
- 2
- 3
輸出結果爲:9
這樣就實現了跨文件的函數調用。
注意: 以下情況會在你使用Python3.5版本中出現,在project目錄下,多了一個__pycache__/pub.cpython-35.pyc文件,它的作用是爲了提高模塊加載的速度,每個模塊都會在__pycache__文件夾中放置該模塊的預編譯模塊,命名爲module.version.pyc,version是模塊的預編譯版本編碼,通常會包含Python的版本號,例如在CPython發行版3.5中,pub.py文件的預編譯文件就是:__pycache__/pub.cpython-35.pyc。
3.6.3 跨目錄模塊調用
如果調用文件與被調用文件在一個目錄下面,那麼可以使用上面的方法,但是如果不在同一個目錄下,假設文件目錄結構如下:
<span style="color:#000000"><code><span style="color:#880000">project/</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">model/</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">pub</span><span style="color:#009900">.</span><span style="color:#880000">py</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">count</span><span style="color:#009900">.</span><span style="color:#880000">py</span></code></span>
- 1
- 2
- 3
- 4
如果還還想在count.py中調用add方法,則需要將目錄的完整路徑補全,eg:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> model.pub <span style="color:#000088">import</span> add
<span style="color:#000088">print</span> add(<span style="color:#006666">4</span>, <span style="color:#006666">5</span>)</code></span>
- 1
- 2
- 3
運行結果,依然是:9
3.6.4 進一步討論跨目錄模塊調用
目錄結構更加複雜的情況:
<span style="color:#000000"><code><span style="color:#880000">project/</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">model/</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">count</span><span style="color:#009900">.</span><span style="color:#880000">py</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">new_count</span><span style="color:#009900">.</span><span style="color:#880000">py</span>
<span style="color:#880000">|</span><span style="color:#006666">-</span><span style="color:#006666">-</span><span style="color:#880000">test</span><span style="color:#009900">.</span><span style="color:#880000">py</span></code></span>
- 1
- 2
- 3
- 4
- 5
count.py代碼如下:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">class</span> <span style="color:#4f4f4f">A</span><span style="color:#4f4f4f">()</span>:
<span style="color:#000088">def</span> <span style="color:#009900">add</span><span style="color:#4f4f4f">(self, a, b)</span>:
<span style="color:#000088">return</span> a + b</code></span>
- 1
- 2
- 3
- 4
new_count.py代碼如下:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> count <span style="color:#000088">import</span> A
<span style="color:#000088">class</span> <span style="color:#4f4f4f">B</span><span style="color:#4f4f4f">(A)</span>:
<span style="color:#000088">def</span> <span style="color:#009900">sub</span><span style="color:#4f4f4f">(self, a, b)</span>:
<span style="color:#000088">return</span> a - b
resule = B().add(<span style="color:#006666">2</span>, <span style="color:#006666">5</span>)
<span style="color:#000088">print</span> resule</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
輸出結果:7
上述結果沒問題,接下來與model目錄平級創建test.py文件:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> model <span style="color:#000088">import</span> new_count
test = new_count()
test.add(<span style="color:#006666">2</span>, <span style="color:#006666">5</span>)</code></span>
- 1
- 2
- 3
- 4
輸出結果,會出現:ImportError: No module named 'count'
通過提示信息,在new_count.py文件中,找不到“count”模塊,可剛纔在執行new_count.py時是可以正常運行的,那麼,要想弄清楚錯誤的原因,首先要知道當Python執行import時到底做了哪些操作?
重點:
當Python在執行import語句時,執行了如下操作:
-
第1步:創建一個新的module對象(它可能包含多個module);
-
第2步:把這個module對象插到sys.module中;
-
第3步:裝載module的代碼(如果需要,則必須先編譯);
-
第4步:執行新的module中對應的代碼;
在執行第3步的時候,首先需要找到module程序所在的位置,搜索的順序是:
當前路徑(以及從當前目錄指定的sys.path),PythonPATH,再後是Python安裝時設置的相關的默認路徑。正因爲存在這樣的順序,所以如果當前路徑或PythonPATH中存在於標準module同樣的module,則會覆蓋標準module。也就是說,如果當前目錄下存在xml.py,那麼在執行import xml時導入的就是當前目錄下的module,而不是系統標準的xml。
瞭解了這些後,我們就可以先構建一個package,以普通module的方式導入,這樣即可直接訪問此package中各個module,注意,Python2中的package必須包含一個__init__.py的文件。
所以上面問題的錯誤原因就是:
站在new_count.py的位置,執行from count import A
,可查看當前目錄下是否存在“count”名字的文件或目錄,是可以找到的,但是站在test.py的位置,執行from count import A
時,在當前目錄下是找不到“count”名字的文件或目錄的,所以拋出異常。
解決辦法:
最簡單的辦法就是將導入方法修改爲from .count import A
,在“count”前面加個點,用來告訴程序count是相對於new_content.py的一個導入。
上面解決辦法引入的新的問題:
修改new_count.py代碼如下:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> .count <span style="color:#000088">import</span> A
<span style="color:#000088">class</span> <span style="color:#4f4f4f">B</span><span style="color:#4f4f4f">(A)</span>:
<span style="color:#000088">def</span> <span style="color:#009900">sub</span><span style="color:#4f4f4f">(self, a, b)</span>:
<span style="color:#000088">return</span> a - b
result = B().add(<span style="color:#006666">2</span>, <span style="color:#006666">5</span>)
<span style="color:#000088">print</span> result</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
當再次執行test.py代碼時,出現了新的錯誤:
<span style="color:#000000"><code class="language-syslog">Traceback (most recent <span style="color:#000088">call</span> <span style="color:#000088">last</span>):
File <span style="color:#009900">"/tmp/project/model/new_count.py"</span>, line <span style="color:#006666">1</span>, <span style="color:#000088">in</span> <<span style="color:#000088">module</span>>
<span style="color:#000088">from</span> .<span style="color:#009900">count</span> import A
[Finished <span style="color:#000088">in</span> <span style="color:#006666">0.1</span>s <span style="color:#000088">with</span> exit code <span style="color:#006666">1</span>]SystemError: Parent <span style="color:#000088">module</span> <span style="color:#009900">''</span> <span style="color:#000088">not</span> loaded, cannot perform <span style="color:#000088">relative</span> import</code></span>
- 1
- 2
- 3
- 4
這句話的意思是:“未加載父模塊,不能執行相對導入”。
解決辦法:
需要將導入模塊所在目錄添加到系統環境變量PATH目錄下纔可以。
修改test.py的代碼:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">import</span> sys
sys.path.append(<span style="color:#009900">"./model"</span>) <span style="color:#880000">#將model目錄添加到系統環境變量path下</span>
<span style="color:#000088">from</span> model <span style="color:#000088">import</span> new_count
test = new_count()
test.add(<span style="color:#006666">2</span>, <span style="color:#006666">5</span>)</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
輸出結果:7,注意如果是python2版本需要在model目錄下創建init文件才行。
3.7 異常
Python用異常對象(exception object)來表示異常情況。遇到錯誤後,會引發異常,如果異常對象並未被處理或者捕捉,則程序就會用所謂的回溯(Traceback,一種錯誤信息)來終止執行。
3.7.1 認識異常
看下面的代碼:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span>open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">'r'</span>)
Traceback (most recent call last):
File <span style="color:#009900">"<stdin>"</span>, line <span style="color:#006666">1</span>, <span style="color:#000088">in</span> <module>
IOError: [Errno <span style="color:#006666">2</span>] No such file <span style="color:#000088">or</span> directory: <span style="color:#009900">'abc.txt'</span></code></span>
- 1
- 2
- 3
- 4
錯誤很明顯,我們根本沒創建這個文件,自然也無法open操作。我們可以視線捕捉這個異常:Python通過try…except…語句來接收並處理這個異常。
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span> open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">"r"</span>)
<span style="color:#006666">... </span><span style="color:#000088">except</span> IOError:
<span style="color:#006666">... </span> <span style="color:#000088">print</span> <span style="color:#009900">"異常了"</span>
<span style="color:#006666">... </span>
異常了</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
注意: 我們這裏使用的仍然是Python2版本,所以和書中的Python3版本略有不同,以下都是按Python2版本進行演示的。
再來看下面的例子:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span> <span style="color:#000088">print</span> aa
<span style="color:#006666">... </span><span style="color:#000088">except</span> IOError:
<span style="color:#006666">... </span> <span style="color:#000088">print</span> <span style="color:#009900">"異常了"</span>
<span style="color:#006666">... </span>
Traceback (most recent call last):
File <span style="color:#009900">"<stdin>"</span>, line <span style="color:#006666">2</span>, <span style="color:#000088">in</span> <module>
NameError: name <span style="color:#009900">'aa'</span> <span style="color:#000088">is</span> <span style="color:#000088">not</span> defined</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
上面的例子,雖然捕捉異常,但是由於捕捉的異常和實際異常的錯誤類型並不相符,所以導致失效。
只需要更換一個正確的接收異常的類型就可以了:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span> <span style="color:#000088">print</span> aa
<span style="color:#006666">... </span><span style="color:#000088">except</span> NameError:
<span style="color:#006666">... </span> <span style="color:#000088">print</span> <span style="color:#009900">"異常了"</span>
<span style="color:#006666">... </span>
異常了</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
那麼,程序是怎麼拋出不同類型的錯誤呢?
異常的拋出機制:
- 如果在運行時發生異常,則解釋器會查找相應的處理語句(稱爲handler);
- 如果在當前函數裏沒有找到的話,則它會將異常傳遞給上層的調用函數,看看那裏能不能處理;
- 如果在最外層(全局main)還是沒有找到的話,那麼解釋器就會退出,同時打印出Traceback,以便讓用戶找到錯誤產生的原因。
注意: 異常不一定等於錯誤,有時候它只是一個警告,有時候它只是一個終止信號,例如退出循環等。
Python中所有異常都集成Exception,所以可以使用它來接收所有類型的異常:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">try</span>:
open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">"r"</span>)
<span style="color:#000088">except</span> Exception:
<span style="color:#000088">print</span> <span style="color:#009900">"異常了"</span>
異常了</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
從Python 2.5之後,所有的異常類都有了新的基類BaseException,Exception同樣也繼承自BaseException,所以我們可以使用BaseException來接收所有類型的異常:
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span> open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">"r"</span>)
<span style="color:#006666">... </span> <span style="color:#000088">print</span> aa
<span style="color:#006666">... </span><span style="color:#000088">except</span> BaseException:
<span style="color:#006666">... </span> <span style="color:#000088">print</span> <span style="color:#009900">"異常了"</span>
<span style="color:#006666">... </span>
異常了</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
對於這個例子來說,只要其中一行出現了異常就會打印出異常信息,但是如何才能準確知道是哪一行代碼引起的異常呢,又如何讓Python直接告訴我們異常的原因呢?
<span style="color:#000000"><code class="language-python"><span style="color:#006666">>>> </span><span style="color:#000088">try</span>:
<span style="color:#006666">... </span> open(<span style="color:#009900">"abc.txt"</span>, <span style="color:#009900">"r"</span>)
<span style="color:#006666">... </span> <span style="color:#000088">print</span> aa
<span style="color:#006666">... </span><span style="color:#000088">except</span> BaseException, e:
<span style="color:#006666">... </span> <span style="color:#000088">print</span> e
<span style="color:#006666">... </span>
[Errno <span style="color:#006666">2</span>] No such file <span style="color:#000088">or</span> directory: <span style="color:#009900">'abc.txt'</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
這樣就可以打印出異常的詳細信息了。
注意: Python 2中使用“, e”這種方式來捕捉異常詳細信息,而Python 3中使用“as msg”的方式,這是兩者的區別。
Python常見的異常
異常 | 描述 |
---|---|
BaseException | 新的所有異常類的基類 |
Exception | 所有異常類的基類,但繼承BaseException類 |
AssertionError | assert語句失敗 |
FileNotFoundError | 試圖打開一個不存在的文件或目錄 |
AttributeError | 試圖訪問的對象沒有屬性 |
OSError | 當系統函數返回一個系統相關的錯誤,包括I/O故障,如“找不到文件”或“磁盤已滿”時,引發此異常 |
NameError | 使用一個還未賦值對象的變量 |
IndexError | 當一個序列超出了範圍 |
SyntaxError | 當解析器遇到一個語法錯誤時引發 |
KeyboardInterrupt | Ctrl+C被按下,程序被強行終止 |
TypeError | 傳入的對象類型與要求不符 |
3.7.2 更多異常用法
異常的更多用法:try...except...else
<span style="color:#000000"><code class="language-python"><span style="color:#000088">try</span>:
aa = <span style="color:#009900">"異常測試:"</span>
<span style="color:#000088">print</span> aa
<span style="color:#000088">except</span> Exception <span style="color:#000088">as</span> msg:
<span style="color:#000088">print</span> msg
<span style="color:#000088">else</span>:
<span style="color:#000088">print</span> <span style="color:#009900">"沒有異常!"</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
輸出結果:
<span style="color:#000000"><code>異常測試:
沒有異常!</code></span>
- 1
- 2
上面代碼是因爲沒有異常所以執行了else,但是例如文件的關閉、鎖的釋放、把數據庫連接返還給連接池等操作,這些操作無論是否異常都希望可以被執行,就需要用到:try...except...finally...
<span style="color:#000000"><code class="language-python"><span style="color:#000088">try</span>:
<span style="color:#000088">print</span> aa
<span style="color:#000088">except</span> Exception <span style="color:#000088">as</span> e:
<span style="color:#000088">print</span> e
<span style="color:#000088">finally</span>:
<span style="color:#000088">print</span> <span style="color:#009900">"不管是否異常,我都會被執行。"</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
輸出結果:
<span style="color:#000000"><code>name <span style="color:#009900">'aa'</span> is <span style="color:#000088">not</span> <span style="color:#000088">defined</span>
不管是否異常,我都會被執行。</code></span>
- 1
- 2
修改上述代碼,定義aa變量:
<span style="color:#000000"><code class="language-python"><span style="color:#000088">try</span>:
aa = <span style="color:#009900">"異常測試:"</span>
<span style="color:#000088">print</span> aa
<span style="color:#000088">except</span> Exception <span style="color:#000088">as</span> e:
<span style="color:#000088">print</span> e
<span style="color:#000088">finally</span>:
<span style="color:#000088">print</span> <span style="color:#009900">"不管是否異常,我都會被執行。"</span></code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
輸出結果:
<span style="color:#000000"><code class="language-python">異常測試:
不管是否異常,我都會被執行。</code></span>
- 1
- 2
3.7.3 拋出異常
print方法只是打印異常,而raise方法可以拋出一個異常信息。
<span style="color:#000000"><code class="language-python"><span style="color:#000088">from</span> random <span style="color:#000088">import</span> randint
<span style="color:#880000"># 生成一個1到9之間的隨機整數</span>
number = randint(<span style="color:#006666">1</span>, <span style="color:#006666">9</span>)
<span style="color:#000088">if</span> number % <span style="color:#006666">2</span> == <span style="color:#006666">0</span>:
<span style="color:#000088">raise</span> NameError(<span style="color:#009900">"%d is even"</span> % number)
<span style="color:#000088">else</span>:
<span style="color:#000088">raise</span> NameError(<span style="color:#009900">"%d is odd"</span> % number)</code></span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
輸出結果:
<span style="color:#000000"><code class="language-python">Traceback (most recent call last):
File <span style="color:#009900">"<stdin>"</span>, line <span style="color:#006666">4</span>, <span style="color:#000088">in</span> <module>
NameError: <span style="color:#006666">3</span> <span style="color:#000088">is</span> odd</code></span>
- 1
- 2
- 3
判斷奇偶數與NameError之間沒有任何關係,這裏只是爲了演示如何通過raise方法拋出各種類型的異常。
注意: raise只能使用Python中所提供的異常類,如果自定義一個abcError,會提示錯誤abcError未定義。
總結
本章內容只是Python語法的入門的入門,如果想要開始後面的教程,還需要有Python基礎,而最佳快速入門的就是《笨方法學Python》了,有興趣的同學可以搜索並學習。