【慕課網Python基礎課程】Python入門

Python入門

3-1 Python中數據類型

計算機顧名思義就是可以做數學計算的機器,因此,計算機程序理所當然地可以處理各種數值。但是,計算機能處理的遠不止數值,還可以處理文本、圖形、音頻、視頻、網頁等各種各樣的數據,不同的數據,需要定義不同的數據類型。在Python中,能夠直接處理的數據類型有以下幾種:

一、整數

Python可以處理任意大小的整數,當然包括負整數,在Python程序中,整數的表示方法和數學上的寫法一模一樣,例如:1,100,-8080,0,等等。

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

二、浮點數

浮點數也就是小數,之所以稱爲浮點數,是因爲按照科學記數法表示時,一個浮點數的小數點位置是可變的,比如,1.23x10^9和12.3x10^8是相等的。浮點數可以用數學寫法,如1.23,3.14,-9.01,等等。但是對於很大或很小的浮點數,就必須用科學計數法表示,把10用e替代,1.23x10^9就是1.23e9,或者12.3e8,0.000012可以寫成1.2e-5,等等。

整數和浮點數在計算機內部存儲的方式是不同的,整數運算永遠是精確的(除法難道也是精確的?是的!),而浮點數運算則可能會有四捨五入的誤差。

三、字符串

字符串是以''或""括起來的任意文本,比如'abc',"xyz"等等。請注意,''或""本身只是一種表示方式,不是字符串的一部分,因此,字符串'abc'只有a,b,c這3個字符。

四、布爾值

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

布爾值可以用and、or和not運算。

and運算是與運算,只有所有都爲 True,and運算結果纔是 True。

or運算是或運算,只要其中有一個爲 True,or 運算結果就是 True。

not運算是非運算,它是一個單目運算符,把 True 變成 False,False 變成 True。

五、空值

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

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

 

任務

試一試,在右邊編輯器中,完成以下任務:

1. 計算十進制整數 45678 和十六進制整數 0x12fd2 之和。

2. 請用字符串表示出Learn Python in imooc。

3. 請計算以下表達式的布爾值(注意==表示判斷是否相等):

    100 < 99

    0xff == 255

注意:使用print命令

3-2 Python之print語句

print語句可以向屏幕上輸出指定的文字。比如輸出'hello, world',用代碼實現如下:

>>> print 'hello, world'

注意:

1.當我們在Python交互式環境下編寫代碼時,>>>是Python解釋器的提示符,不是代碼的一部分。

2.當我們在文本編輯器中編寫代碼時,千萬不要自己添加 >>>。

print語句也可以跟上多個字符串,用逗號“,”隔開,就可以連成一串輸出:

>>> print 'The quick brown fox', 'jumpsover', '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把它視爲字符串,請自行解釋上述打印結果。

3-4 Python中什麼是變量

在Python中,變量的概念基本上和初中代數的方程變量是一致的。

例如,對於方程式 y=x*x ,x就是變量。當x=2時,計算結果是4,當x=5時,計算結果是25。

只是在計算機程序中,變量不僅可以是數字,還可以是任意數據類型。

在Python程序中,變量是用一個變量名錶示,變量名必須是大小寫英文、數字和下劃線(_)的組合,且不能用數字開頭,比如:

a = 1

變量a是一個整數。

t_007 = 'T007'

變量t_007是一個字符串。

在Python中,等號=是賦值語句,可以把任意數據類型賦值給變量,同一個變量可以反覆賦值,而且可以是不同類型的變量,例如:

a = 123    # a是整數

print a

a = 'imooc'   #a變爲字符串

print a

這種變量本身類型不固定的語言稱之爲動態語言,與之對應的是靜態語言。

靜態語言在定義變量時必須指定變量類型,如果賦值的時候類型不匹配,就會報錯。例如Java是靜態語言,賦值語句如下(// 表示註釋):

int a = 123; // a是整數類型變量

a = "mooc"; // 錯誤:不能把字符串賦給整型變量

和靜態語言相比,動態語言更靈活,就是這個原因。

請不要把賦值語句的等號等同於數學的等號。比如下面的代碼:

x = 10

x = x + 2

如果從數學上理解x = x + 2那無論如何是不成立的,在程序中,賦值語句先計算右側的表達式x + 2,得到結果12,再賦給變量x。由於x之前的值是10,重新賦值後,x的值變成12。

最後,理解變量在計算機內存中的表示也非常重要。當我們寫:a = 'ABC'時,Python解釋器幹了兩件事情:

1. 在內存中創建了一個'ABC'的字符串;

2. 在內存中創建了一個名爲a的變量,並把它指向'ABC'。

也可以把一個變量a賦值給另一個變量b,這個操作實際上是把變量b指向變量a所指向的數據,例如下面的代碼:

a = 'ABC'

b = a

a = 'XYZ'

print b

最後一行打印出變量b的內容到底是'ABC'呢還是'XYZ'?如果從數學意義上理解,就會錯誤地得出b和a相同,也應該是'XYZ',但實際上b的值是'ABC',讓我們一行一行地執行代碼,就可以看到到底發生了什麼事:

執行a = 'ABC',解釋器創建了字符串  'ABC'和變量 a,並把a指向 'ABC':

 

執行b = a,解釋器創建了變量 b,並把b指向 a 指向的字符串'ABC':

 

 

執行a = 'XYZ',解釋器創建了字符串'XYZ',並把a的指向改爲'XYZ',但b並沒有更改:

 

所以,最後打印變量b的結果自然是'ABC'了。

任務

等差數列可以定義爲每一項與它的前一項的差等於一個常數,可以用變量 x1 表示等差數列的第一項,用 d 表示公差,請計算數列

1 4 7 10 13 16 19 ...

前 100 項的和。

注意: ???表示任務,以後章節同理,不再做提示。

3-5 Python中定義字符串

前面我們講解了什麼是字符串。字符串可以用''或者""括起來表示。

如果字符串本身包含'怎麼辦?比如我們要表示字符串 I'm OK ,這時,可以用" "括起來表示:

"I'm OK"

類似的,如果字符串包含",我們就可以用' '括起來表示:

'Learn "Python" in imooc'

如果字符串既包含'又包含"怎麼辦?

這個時候,就需要對字符串的某些特殊字符進行“轉義”,Python字符串用\進行轉義。

要表示字符串 Bob said "I'm OK".

由於 ' 和 " 會引起歧義,因此,我們在它前面插入一個\表示這是一個普通字符,不代表字符串的起始,因此,這個字符串又可以表示爲

'Bob said \"I\'m OK\".'

注意:轉義字符 \ 不計入字符串的內容中。

常用的轉義字符還有:

\n 表示換行

\t 表示一個製表符

\\ 表示 \ 字符本身

任務

請將下面兩行內容用Python的字符串表示並打印出來:

Python was started in 1989 by "Guido".

Python is free and easy to learn.

3-6 Python中raw字符串與多行字符串

如果一個字符串包含很多需要轉義的字符,對每一個字符都進行轉義會很麻煩。爲了避免這種情況,我們可以在字符串前面加個前綴 r ,表示這是一個 raw 字符串,裏面的字符就不需要轉義了。例如:

 

r'\(~_~)/ \(~_~)/'

但是r'...'表示法不能表示多行字符串,也不能表示包含'和 "的字符串(爲什麼?)

如果要表示多行字符串,可以用'''...'''表示:

'''Line 1

Line 2

Line 3'''

上面這個字符串的表示方法和下面的是完全一樣的:

'Line 1\nLine 2\nLine 3'

還可以在多行字符串前面添加 r ,把這個多行字符串也變成一個raw字符串:

r'''Python is created by "Guido".

It is free and easy to learn.

Let's start learn Python in imooc!'''

任務

請把下面的字符串用r'''...'''的形式改寫,並用print打印出來:

'\"To be, or not to be\": that is thequestion.\nWhether it\'s nobler in the mind to suffer.'

3-7 Python中Unicode字符串

字符串還有一個編碼問題。

因爲計算機只能處理數字,如果要處理文本,就必須先把文本轉換爲數字才能處理。最早的計算機在設計時採用8個比特(bit)作爲一個字節(byte),所以,一個字節能表示的最大的整數就是255(二進制11111111=十進制255),0 - 255被用來表示大小寫英文字母、數字和一些符號,這個編碼表被稱爲ASCII編碼,比如大寫字母 A 的編碼是65,小寫字母 z 的編碼是122。

如果要表示中文,顯然一個字節是不夠的,至少需要兩個字節,而且還不能和ASCII編碼衝突,所以,中國製定了GB2312編碼,用來把中文編進去。

類似的,日文和韓文等其他語言也有這個問題。爲了統一所有文字的編碼,Unicode應運而生。Unicode把所有語言都統一到一套編碼裏,這樣就不會再有亂碼問題了。

Unicode通常用兩個字節表示一個字符,原有的英文編碼從單字節變成雙字節,只需要把高字節全部填爲0就可以。

因爲Python的誕生比Unicode標準發佈的時間還要早,所以最早的Python只支持ASCII編碼,普通的字符串'ABC'在Python內部都是ASCII編碼的。

Python在後來添加了對Unicode的支持,以Unicode表示的字符串用u'...'表示,比如:

print u'中文'

中文

注意: 不加 u ,中文就不能正常顯示。

Unicode字符串除了多了一個 u 之外,與普通字符串沒啥區別,轉義字符和多行表示法仍然有效:

轉義:

u'中文\n日文\n韓文'

多行:

u'''第一行

第二行'''

raw+多行:

ur'''Python的Unicode字符串支持"中文",

"日文",

"韓文"等多種語言'''

如果中文字符串在Python環境下遇到 UnicodeDecodeError,這是因爲.py文件保存的格式有問題。可以在第一行添加註釋

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

目的是告訴Python解釋器,用UTF-8編碼讀取源代碼。然後用Notepad++ 另存爲... 並選擇UTF-8格式保存。

任務

用多行Unicode字符串表示下面的唐詩並打印:

靜夜思

牀前明月光,

疑是地上霜。

舉頭望明月,

低頭思故鄉。

3-8 Python中整數和浮點數

Python支持對整數和浮點數直接進行四則混合運算,運算規則和數學上的四則運算規則完全一致。

基本的運算:

1 + 2 + 3   #==> 6

4 * 5 - 6   #==> 14

7.5 / 8 + 2.1  # ==> 3.0375

使用括號可以提升優先級,這和數學運算完全一致,注意只能使用小括號,但是括號可以嵌套很多層:

(1 + 2) * 3    #==> 9

(2.2 + 3.3) / (1.5 * (9 - 0.3))    # ==> 0.42145593869731807

和數學運算不同的地方是,Python的整數運算結果仍然是整數,浮點數運算結果仍然是浮點數:

1 + 2    #==> 整數 3

1.0 + 2.0    #==> 浮點數 3.0

但是整數和浮點數混合運算的結果就變成浮點數了:

1 + 2.0    # ==> 浮點數 3.0

爲什麼要區分整數運算和浮點數運算呢?這是因爲整數運算的結果永遠是精確的,而浮點數運算的結果不一定精確,因爲計算機內存再大,也無法精確表示出無限循環小數,比如 0.1 換成二進制表示就是無限循環小數。

那整數的除法運算遇到除不盡的時候,結果難道不是浮點數嗎?我們來試一下:

11 / 4    #==> 2

令很多初學者驚訝的是,Python的整數除法,即使除不盡,結果仍然是整數,餘數直接被扔掉。不過,Python提供了一個求餘的運算 % 可以計算餘數:

11 % 4    #==> 3

如果我們要計算 11 / 4 的精確結果,按照“整數和浮點數混合運算的結果是浮點數”的法則,把兩個數中的一個變成浮點數再運算就沒問題了:

11.0 / 4    #==> 2.75

任務

請計算 2.5 + 10 / 4 ,並解釋計算結果爲什麼不是期望的 5.0 ?

請修復上述運算,使得計算結果是 5.0

3-9 Python中布爾類型

我們已經瞭解了Python支持布爾類型的數據,布爾類型只有True和False兩種值,但是布爾類型有以下幾種運算:

與運算:只有兩個布爾值都爲 True 時,計算結果才爲 True。

True and True  # ==> True

True and False  # ==> False

False and True  # ==> False

False and False  # ==> False

或運算:只要有一個布爾值爲 True,計算結果就是 True。

True or True   #==> True

True or False  # ==> True

False or True  # ==> True

False or False  # ==> False

非運算:把True變爲False,或者把False變爲True:

not True   #==> False

not False   #==> True

布爾運算在計算機中用來做條件判斷,根據計算結果爲True或者False,計算機可以自動執行不同的後續代碼。

在Python中,布爾類型還可以與其他數據類型做 and、or和not運算,請看下面的代碼:

a = True

print a and 'a=T' or 'a=F'

計算結果不是布爾類型,而是字符串 'a=T',這是爲什麼呢?

因爲Python把0、空字符串''和None看成 False,其他數值和非空字符串都看成 True,所以:

True and 'a=T' 計算結果是 'a=T'

繼續計算 'a=T' or 'a=F' 計算結果還是 'a=T'

要解釋上述結果,又涉及到 and 和 or 運算的一條重要法則:短路計算。

1. 在計算 a and b 時,如果 a 是 False,則根據與運算法則,整個結果必定爲 False,因此返回 a;如果 a 是 True,則整個計算結果必定取決與 b,因此返回 b。

2. 在計算 a or b 時,如果 a 是 True,則根據或運算法則,整個計算結果必定爲 True,因此返回 a;如果 a 是 False,則整個計算結果必定取決於 b,因此返回 b。

所以Python解釋器在做布爾運算時,只要能提前確定計算結果,它就不會往後算了,直接返回結果。

任務

請運行如下代碼,並解釋打印的結果:

a = 'python'

print 'hello,', a or 'world'

b = ''

print 'hello,', b or 'world'

4-1 Python創建list

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

比如,列出班裏所有同學的名字,就可以用一個list表示:

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

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

list是數學意義上的有序集合,也就是說,list中的元素是按照順序排列的。

構造list非常簡單,按照上面的代碼,直接用 [ ] 把list的所有元素都括起來,就是一個list對象。通常,我們會把list賦值給一個變量,這樣,就可以通過變量來引用list:

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

>>> classmates # 打印classmates變量的內容

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

由於Python是動態語言,所以list中包含的元素並不要求都必須是同一種數據類型,我們完全可以在list中包含各種數據:

>>> L = ['Michael', 100, True]

一個元素也沒有的list,就是空list:

>>> empty_list = []

任務

假設班裏有3名同學:Adam,Lisa和Bart,他們的成績分別是 95.5,85 和 59,請按照 名字, 分數, 名字, 分數... 的順序按照分數從高到低用一個list表示,然後打印出來。

4-2 Python按照索引訪問list

由於list是一個有序集合,所以,我們可以用一個list按分數從高到低表示出班裏的3個同學:

>>> L = ['Adam', 'Lisa', 'Bart']

那我們如何從list中獲取指定第 N 名的同學呢?方法是通過索引來獲取list中的指定元素。

需要特別注意的是,索引從 0 開始,也就是說,第一個元素的索引是0,第二個元素的索引是1,以此類推。

因此,要打印第一名同學的名字,用 L[0]:

>>> print L[0]

Adam

要打印第二名同學的名字,用 L[1]:

>>> print L[1]

Lisa

要打印第三名同學的名字,用 L[2]:

>>> print L[2]

Bart

要打印第四名同學的名字,用 L[3]:

>>> print L[3]

Traceback (most recent call last):

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

IndexError: list index out of range

報錯了!IndexError意思就是索引超出了範圍,因爲上面的list只有3個元素,有效的索引是 0,1,2。

所以,使用索引時,千萬注意不要越界。

任務

三名同學的成績可以用一個list表示:

L = [95.5, 85, 59]

請按照索引分別打印出第一名、第二名、第三名,同時測試 print L[3]。

4-3 Python之倒序訪問list

我們還是用一個list按分數從高到低表示出班裏的3個同學:

>>> L = ['Adam', 'Lisa', 'Bart']

這時,老師說,請分數最低的同學站出來。

要寫代碼完成這個任務,我們可以先數一數這個 list,發現它包含3個元素,因此,最後一個元素的索引是2:

>>> print L[2]

Bart

有沒有更簡單的方法?

有!

Bart同學是最後一名,俗稱倒數第一,所以,我們可以用 -1 這個索引來表示最後一個元素:

>>> print L[-1]

Bart

Bart同學表示躺槍。

類似的,倒數第二用 -2 表示,倒數第三用 -3 表示,倒數第四用 -4 表示:

>>> print L[-2]

Lisa

>>> print L[-3]

Adam

>>> print L[-4]

Traceback (most recent call last):

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

IndexError: list index out of range

L[-4] 報錯了,因爲倒數第四不存在,一共只有3個元素。

使用倒序索引時,也要注意不要越界。

任務

三名同學的成績可以用一個list表示:

L = [95.5, 85, 59]

請按照倒序索引分別打印出倒數第一、倒數第二、倒數第三。

4-4 Python之添加新元素

現在,班裏有3名同學:

>>> L = ['Adam', 'Lisa', 'Bart']

今天,班裏轉來一名新同學 Paul,如何把新同學添加到現有的 list 中呢?

第一個辦法是用 list 的 append() 方法,把新同學追加到 list 的末尾:

>>> L = ['Adam', 'Lisa', 'Bart']

>>> L.append('Paul')

>>> print L

['Adam', 'Lisa', 'Bart', 'Paul']

append()總是把新的元素添加到 list 的尾部。

如果 Paul 同學表示自己總是考滿分,要求添加到第一的位置,怎麼辦?

方法是用list的 insert()方法,它接受兩個參數,第一個參數是索引號,第二個參數是待添加的新元素:

>>> L = ['Adam', 'Lisa', 'Bart']

>>> L.insert(0, 'Paul')

>>> print L

['Paul', 'Adam', 'Lisa', 'Bart']

L.insert(0, 'Paul') 的意思是,'Paul'將被添加到索引爲 0 的位置上(也就是第一個),而原來索引爲 0 的Adam同學,以及後面的所有同學,都自動向後移動一位。

任務

假設新來一名學生Paul,Paul 同學的成績比Bart好,但是比Lisa差,他應該排到第三名的位置,請用代碼實現。

4-5 Python從list刪除元素

Paul同學剛來幾天又要轉走了,那麼我們怎麼把Paul 從現有的list中刪除呢?

如果Paul同學排在最後一個,我們可以用list的pop()方法刪除:

>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']

>>> L.pop()

'Paul'

>>> print L

['Adam', 'Lisa', 'Bart']

pop()方法總是刪掉list的最後一個元素,並且它還返回這個元素,所以我們執行 L.pop() 後,會打印出 'Paul'。

如果Paul同學不是排在最後一個怎麼辦?比如Paul同學排在第三:

>>> L = ['Adam', 'Lisa', 'Paul', 'Bart']

要把Paul踢出list,我們就必須先定位Paul的位置。由於Paul的索引是2,因此,用 pop(2)把Paul刪掉:

>>> L.pop(2)

'Paul'

>>> print L

['Adam', 'Lisa', 'Bart']

任務

注意右邊編輯器代碼中 list 如下:

L = ['Adam', 'Lisa', 'Paul', 'Bart']

Paul的索引是2,Bart的索引是3,如果我們要把Paul和Bart都刪掉,請解釋下面的代碼爲什麼不能正確運行:

L.pop(2)

L.pop(3)

怎樣調整代碼可以把Paul和Bart都正確刪除掉?

4-6 Python中替換元素

假設現在班裏仍然是3名同學:

>>> L = ['Adam', 'Lisa', 'Bart']

現在,Bart同學要轉學走了,碰巧來了一個Paul同學,要更新班級成員名單,我們可以先把Bart刪掉,再把Paul添加進來。

另一個辦法是直接用Paul把Bart給替換掉:

>>> L[2] = 'Paul'

>>> print L

L = ['Adam', 'Lisa', 'Paul']

對list中的某一個索引賦值,就可以直接用新的元素替換掉原來的元素,list包含的元素個數保持不變。

由於Bart還可以用 -1 做索引,因此,下面的代碼也可以完成同樣的替換工作:

>>> L[-1] = 'Paul'

任務

班裏的同學按照分數排名是這樣的:

L = ['Adam', 'Lisa', 'Bart']

但是,在一次考試後,Bart同學意外取得第一,而Adam同學考了倒數第一。

請通過對list的索引賦值,生成新的排名。

4-7 Python之創建tuple

tuple是另一種有序的列表,中文翻譯爲“ 元組 ”。tuple 和 list 非常類似,但是,tuple一旦創建完畢,就不能修改了。

同樣是表示班裏同學的名稱,用tuple表示如下:

>>> t = ('Adam', 'Lisa', 'Bart')

創建tuple和創建list唯一不同之處是用( )替代了[ ]。

現在,這個 t 就不能改變了,tuple沒有 append()方法,也沒有insert()和pop()方法。所以,新同學沒法直接往 tuple 中添加,老同學想退出 tuple 也不行。

獲取 tuple 元素的方式和 list 是一模一樣的,我們可以正常使用 t[0],t[-1]等索引方式訪問元素,但是不能賦值成別的元素,不信可以試試:

>>> t[0] = 'Paul'

Traceback (most recent call last):

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

TypeError: 'tuple' object does not support itemassignment

任務

創建一個tuple,順序包含0 - 9這10個數。

4-8 Python之創建單元素tuple

tuple和list一樣,可以包含 0 個、1個和任意多個元素。

包含多個元素的 tuple,前面我們已經創建過了。

包含 0 個元素的 tuple,也就是空tuple,直接用 ()表示:

>>> t = ()

>>> print t

()

創建包含1個元素的 tuple 呢?來試試:

>>> t = (1)

>>> print t

1

好像哪裏不對!t 不是 tuple ,而是整數1。爲什麼呢?

因爲()既可以表示tuple,又可以作爲括號表示運算時的優先級,結果 (1) 被Python解釋器計算出結果 1,導致我們得到的不是tuple,而是整數 1。

正是因爲用()定義單元素的tuple有歧義,所以 Python 規定,單元素 tuple 要多加一個逗號“,”,這樣就避免了歧義:

>>> t = (1,)

>>> print t

(1,)

Python在打印單元素tuple時,也自動添加了一個“,”,爲了更明確地告訴你這是一個tuple。

多元素 tuple 加不加這個額外的“,”效果是一樣的:

>>> t = (1, 2, 3,)

>>> print t

(1, 2, 3)

任務

請指出右邊編輯器中代碼爲什麼沒有創建出包含一個學生的 tuple:

t = ('Adam')

print t

請修改代碼,確保 t 是一個tuple。

4-9 Python之“可變”的tuple

前面我們看到了tuple一旦創建就不能修改。現在,我們來看一個“可變”的tuple:

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

注意到 t 有 3 個元素:'a','b'和一個list:['A', 'B']。list作爲一個整體是tuple的第3個元素。list對象可以通過 t[2] 拿到:

>>> L = t[2]

然後,我們把list的兩個元素改一改:

>>> L[0] = 'X'

>>> L[1] = 'Y'

再看看tuple的內容:

>>> print t

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

不是說tuple一旦定義後就不可變了嗎?怎麼現在又變了?

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

 

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

 

 

表面上看,tuple的元素確實變了,但其實變的不是 tuple 的元素,而是list的元素。

tuple一開始指向的list並沒有改成別的list,所以,tuple所謂的“不變”是說,tuple的每個元素,指向永遠不變。即指向'a',就不能改成指向'b',指向一個list,就不能改成指向其他對象,但指向的這個list本身是可變的!

理解了“指向不變”後,要創建一個內容也不變的tuple怎麼做?那就必須保證tuple的每一個元素本身也不能變。

任務

定義了tuple:

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

由於 t 包含一個list元素,導致tuple的內容是可變的。能否修改上述代碼,讓tuple內容不可變?

5-1 Python之if語句

計算機之所以能做很多自動化的任務,因爲它可以自己做條件判斷。

比如,輸入用戶年齡,根據年齡打印不同的內容,在Python程序中,可以用if語句實現:

age = 20

if age >= 18:

    print 'yourage is', age

    print'adult'

print 'END'

注意: Python代碼的縮進規則。具有相同縮進的代碼被視爲代碼塊,上面的3,4行 print 語句就構成一個代碼塊(但不包括第5行的print)。如果 if 語句判斷爲 True,就會執行這個代碼塊。

縮進請嚴格按照Python的習慣寫法:4個空格,不要使用Tab,更不要混合Tab和空格,否則很容易造成因爲縮進引起的語法錯誤。

注意: if 語句後接表達式,然後用:表示代碼塊開始。

如果你在Python交互環境下敲代碼,還要特別留意縮進,並且退出縮進需要多敲一行回車:

>>> age = 20

>>> if age >= 18:

...     print'your age is', age

...     print'adult'

...

your age is 20

adult

任務

如果成績達到60分或以上,視爲passed。

假設Bart同學的分數是75,請用if語句判斷是否能打印出 passed:

5-2 Python之if-else

當 if 語句判斷表達式的結果爲 True 時,就會執行 if 包含的代碼塊:

if age >= 18:

    print'adult'

如果我們想判斷年齡在18歲以下時,打印出 'teenager',怎麼辦?

方法是再寫一個 if:

if age < 18:

    print'teenager'

或者用 not 運算:

if not age >= 18:

    print'teenager'

細心的同學可以發現,這兩種條件判斷是“非此即彼”的,要麼符合條件1,要麼符合條件2,因此,完全可以用一個 if ... else ... 語句把它們統一起來:

if age >= 18:

    print'adult'

else:

    print'teenager'

利用 if ... else ... 語句,我們可以根據條件表達式的值爲 True 或者 False ,分別執行 if 代碼塊或者 else 代碼塊。

注意: else 後面有個“:”。

任務

如果成績達到60分或以上,視爲passed,否則視爲failed。

假設Bart同學的分數是55,請用if語句打印出 passed 或者 failed:

5-3 Python之if-elif-else

有的時候,一個 if ... else ... 還不夠用。比如,根據年齡的劃分:

條件1:18歲或以上:adult

條件2:6歲或以上:teenager

條件3:6歲以下:kid

我們可以用一個 if age >= 18 判斷是否符合條件1,如果不符合,再通過一個 if 判斷 age >= 6 來判斷是否符合條件2,否則,執行條件3:

if age >= 18:

    print'adult'

else:

    if age >=6:

        print'teenager'

    else:

        print'kid'

這樣寫出來,我們就得到了一個兩層嵌套的 if ... else ... 語句。這個邏輯沒有問題,但是,如果繼續增加條件,比如3歲以下是 baby:

if age >= 18:

    print'adult'

else:

    if age >=6:

        print'teenager'

    else:

        if age>= 3:

           print 'kid'

        else:

           print 'baby'

這種縮進只會越來越多,代碼也會越來越難看。

要避免嵌套結構的 if ... else ...,我們可以用 if ... 多個elif ... else ... 的結構,一次寫完所有的規則:

if age >= 18:

    print 'adult'

elif age >= 6:

    print'teenager'

elif age >= 3:

    print 'kid'

else:

    print 'baby'

elif 意思就是 else if。這樣一來,我們就寫出了結構非常清晰的一系列條件判斷。

特別注意: 這一系列條件判斷會從上到下依次判斷,如果某個判斷爲 True,執行完對應的代碼塊,後面的條件判斷就直接忽略,不再執行了。

請思考下面的代碼:

age = 8

if age >= 6:

    print'teenager'

elif age >= 18:

    print'adult'

else:

    print 'kid'

當 age = 8 時,結果正確,但 age = 20 時,爲什麼沒有打印出 adult?

如果要修復,應該如何修復?

任務

如果按照分數劃定結果:

    90分或以上:excellent

    80分或以上:good

    60分或以上:passed

    60分以下:failed

請編寫程序根據分數打印結果。

5-4 Python之for循環

list或tuple可以表示一個有序集合。如果我們想依次訪問一個list中的每一個元素呢?比如 list:

L = ['Adam', 'Lisa', 'Bart']

print L[0]

print L[1]

print L[2]

如果list只包含幾個元素,這樣寫還行,如果list包含1萬個元素,我們就不可能寫1萬行print。

這時,循環就派上用場了。

Python的 for 循環就可以依次把list或tuple的每個元素迭代出來:

L = ['Adam', 'Lisa', 'Bart']

for name in L:

    print name

注意:  name 這個變量是在 for 循環中定義的,意思是,依次取出list中的每一個元素,並把元素賦值給 name,然後執行for循環體(就是縮進的代碼塊)。

這樣一來,遍歷一個list或tuple就非常容易了。

任務

班裏考試後,老師要統計平均成績,已知4位同學的成績用list表示如下:

L = [75, 92, 59, 68]

請利用for循環計算出平均成績。

5-5 Python之while循環

和 for 循環不同的另一種循環是 while 循環,while 循環不會迭代 list 或 tuple 的元素,而是根據表達式判斷循環是否結束。

比如要從 0 開始打印不大於 N 的整數:

N = 10

x = 0

while x < N:

    print x

    x = x + 1

while循環每次先判斷 x < N,如果爲True,則執行循環體的代碼塊,否則,退出循環。

在循環體內,x = x + 1 會讓 x 不斷增加,最終因爲 x < N 不成立而退出循環。

如果沒有這一個語句,while循環在判斷 x < N 時總是爲True,就會無限循環下去,變成死循環,所以要特別留意while循環的退出條件。

任務

利用while循環計算100以內奇數的和。

while循環的退出條件可設定爲 x < 100

參考代碼:

sum = 0

x = 1

while x < 100:

   sum = sum + x

   x = x + 2

print sum

5-6 Python之break退出循環

用 for 循環或者 while 循環時,如果要在循環體內直接退出循環,可以使用 break 語句。

比如計算1至100的整數和,我們用while來實現:

sum = 0

x = 1

while True:

    sum = sum +x

    x = x + 1

    if x >100:

        break

print sum

咋一看, while True 就是一個死循環,但是在循環體內,我們還判斷了 x > 100 條件成立時,用break語句退出循環,這樣也可以實現循環的結束。

5-7 Python之continue繼續循環

在循環過程中,可以用break退出當前循環,還可以用continue跳過後續循環代碼,繼續下一次循環。

假設我們已經寫好了利用for循環計算平均分的代碼:

L = [75, 98, 59, 81, 66, 43, 69, 85]

sum = 0.0

n = 0

for x in L:

    sum = sum +x

    n = n + 1

print sum / n

現在老師只想統計及格分數的平均分,就要把 x < 60 的分數剔除掉,這時,利用 continue,可以做到當 x < 60的時候,不繼續執行循環體的後續代碼,直接進入下一次循環:

for x in L:

    if x <60:

        continue

    sum = sum +x

    n = n + 1

5-8 Python之 多重循環

在循環內部,還可以嵌套循環,我們來看一個例子:

for x in ['A', 'B', 'C']:

    for y in['1', '2', '3']:

        print x+ y

x 每循環一次,y 就會循環 3 次,這樣,我們可以打印出一個全排列:

A1

A2

A3

B1

B2

B3

C1

C2

C3

6-1 Python之什麼是dict

我們已經知道,list 和 tuple 可以用來表示順序集合,例如,班裏同學的名字:

['Adam', 'Lisa', 'Bart']

或者考試的成績列表:

[95, 85, 59]

但是,要根據名字找到對應的成績,用兩個 list 表示就不方便。

如果把名字和分數關聯起來,組成類似的查找表:

'Adam' ==> 95

'Lisa' ==> 85

'Bart' ==> 59

給定一個名字,就可以直接查到分數。

Python的 dict 就是專門幹這件事的。用 dict 表示“名字”-“成績”的查找表如下:

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

我們把名字稱爲key,對應的成績稱爲value,dict就是通過 key 來查找 value。

花括號 {} 表示這是一個dict,然後按照 key: value, 寫出來即可。最後一個 key: value 的逗號可以省略。

由於dict也是集合,len() 函數可以計算任意集合的大小:

>>> len(d)

3

注意: 一個 key-value 算一個,因此,dict大小爲3。

任務

新來的Paul同學成績是 75 分,請編寫一個dict,把Paul同學的成績也加進去。

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

按照 key: value 的格式寫出 'Paul': 75

參考代碼:

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59,

    'Paul': 75

}

6-2 Python之訪問dict

我們已經能創建一個dict,用於表示名字和成績的對應關係:

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

那麼,如何根據名字來查找對應的成績呢?

可以簡單地使用 d[key] 的形式來查找對應的 value,這和 list 很像,不同之處是,list 必須使用索引返回對應的元素,而dict使用key:

>>> print d['Adam']

95

>>> print d['Paul']

Traceback (most recent call last):

  File"index.py", line 11, in <module>

    printd['Paul']

KeyError: 'Paul'

注意: 通過 key 訪問 dict 的value,只要 key 存在,dict就返回對應的value。如果key不存在,會直接報錯:KeyError。

要避免 KeyError 發生,有兩個辦法:

一是先判斷一下 key 是否存在,用 in 操作符:

if 'Paul' in d:

    printd['Paul']

如果 'Paul' 不存在,if語句判斷爲False,自然不會執行 print d['Paul'] ,從而避免了錯誤。

二是使用dict本身提供的一個 get 方法,在Key不存在的時候,返回None:

>>> print d.get('Bart')

59

>>> print d.get('Paul')

None

任務

根據如下dict:

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

請打印出:

Adam: 95

Lisa: 85

Bart: 59

參考代碼:

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

print 'Adam:', d['Adam']

print 'Lisa:', d['Lisa']

print 'Bart:', d['Bart']

6-3 Python中dict的特點

dict的第一個特點是查找速度快,無論dict有10個元素還是10萬個元素,查找速度都一樣。而list的查找速度隨着元素增加而逐漸下降。

不過dict的查找速度快不是沒有代價的,dict的缺點是佔用內存大,還會浪費很多內容,list正好相反,佔用內存小,但是查找速度慢。

由於dict是按 key 查找,所以,在一個dict中,key不能重複。

dict的第二個特點就是存儲的key-value序對是沒有順序的!這和list不一樣:

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

當我們試圖打印這個dict時:

>>> print d

{'Lisa': 85, 'Adam': 95, 'Bart': 59}

打印的順序不一定是我們創建時的順序,而且,不同的機器打印的順序都可能不同,這說明dict內部是無序的,不能用dict存儲有序的集合。

dict的第三個特點是作爲 key 的元素必須不可變,Python的基本類型如字符串、整數、浮點數都是不可變的,都可以作爲 key。但是list是可變的,就不能作爲 key。

可以試試用list作爲key時會報什麼樣的錯誤。

不可變這個限制僅作用於key,value是否可變無所謂:

{

    '123': [1,2, 3],  # key 是 str,value是list

    123:'123',  # key 是 int,value 是 str

    ('a', 'b'):True  # key 是 tuple,並且tuple的每個元素都是不可變對象,value是 boolean

}

最常用的key還是字符串,因爲用起來最方便。

任務

請設計一個dict,可以根據分數來查找名字,已知成績如下:

Adam: 95,

Lisa: 85,

Bart: 59.

根據分數查找名字時,分數是 key,而名字是 value。

參考代碼:

d = {

    95: 'Adam',

    85: 'Lisa',

    59: 'Bart'

}

6-4 Python更新dict

dict是可變的,也就是說,我們可以隨時往dict中添加新的 key-value。比如已有dict:

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

要把新同學'Paul'的成績 72 加進去,用賦值語句:

>>> d['Paul'] = 72

再看看dict的內容:

>>> print d

{'Lisa': 85, 'Paul': 72, 'Adam': 95, 'Bart': 59}

如果 key 已經存在,則賦值會用新的 value 替換掉原來的 value:

>>> d['Bart'] = 60

>>> print d

{'Lisa': 85, 'Paul': 72, 'Adam': 95, 'Bart': 60}

任務

請根據Paul的成績 72 更新下面的dict:

d = {

    95: 'Adam',

    85: 'Lisa',

    59: 'Bart'

}

以 72 作爲key,'Paul'作爲value添加到dict。

參考代碼:

d = {

    95: 'Adam',

    85: 'Lisa',

    59: 'Bart'

}

d[72] = 'Paul'

6-5 Python之 遍歷dict

由於dict也是一個集合,所以,遍歷dict和遍歷list類似,都可以通過 for 循環實現。

直接使用for循環可以遍歷 dict 的 key:

>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59}

>>> for key in d:

...     printkey

...

Lisa

Adam

Bart

由於通過 key 可以獲取對應的 value,因此,在循環體內,可以獲取到value的值。

任務:請用 for 循環遍歷如下的dict,打印出 name: score 來。

d = {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

通過d[key]獲取對應的value。

參考代碼:

d= {

    'Adam': 95,

    'Lisa': 85,

    'Bart': 59

}

for key in d:

    print key +':', d[key]

6-6 Python中什麼是set

dict的作用是建立一組 key 和一組 value 的映射關係,dict的key是不能重複的。

有的時候,我們只想要 dict 的 key,不關心 key 對應的 value,目的就是保證這個集合的元素不會重複,這時,set就派上用場了。

set 持有一系列元素,這一點和 list 很像,但是set的元素沒有重複,而且是無序的,這點和 dict 的 key很像。

創建 set 的方式是調用 set() 並傳入一個 list,list的元素將作爲set的元素:

>>> s = set(['A', 'B', 'C'])

可以查看 set 的內容:

>>> print s

set(['A', 'C', 'B'])

請注意,上述打印的形式類似 list, 但它不是 list,仔細看還可以發現,打印的順序和原始 list 的順序有可能是不同的,因爲set內部存儲的元素是無序的。

因爲set不能包含重複的元素,所以,當我們傳入包含重複元素的 list 會怎麼樣呢?

>>> s = set(['A', 'B', 'C', 'C'])

>>> print s

set(['A', 'C', 'B'])

>>> len(s)

3

結果顯示,set會自動去掉重複的元素,原來的list有4個元素,但set只有3個元素。

任務

請用set表示班裏的4位同學:

Adam, Lisa, Bart, Paul

創建set前,先創建一個list。

參考代碼:

s = set(['Adam', 'Lisa', 'Bart', 'Paul'])

6-7 Python之 訪問set

由於set存儲的是無序集合,所以我們沒法通過索引來訪問。

訪問 set中的某個元素實際上就是判斷一個元素是否在set中。

例如,存儲了班裏同學名字的set:

>>> s = set(['Adam', 'Lisa', 'Bart', 'Paul'])

我們可以用 in 操作符判斷:

Bart是該班的同學嗎?

>>> 'Bart' in s

True

Bill是該班的同學嗎?

>>> 'Bill' in s

False

bart是該班的同學嗎?

>>> 'bart' in s

False

看來大小寫很重要,'Bart' 和 'bart'被認爲是兩個不同的元素。

任務

由於上述set不能識別小寫的名字,請改進set,使得 'adam' 和 'bart'都能返回True。

在list中,需要把兩個名字同時放進去。

參考代碼:

s = set(['Adam', 'adam', 'Lisa', 'lisa', 'Bart','bart', 'Paul', 'paul'])

print 'adam' in s

print 'bart' in s

6-8 Python之set的特點

set的內部結構和dict很像,唯一區別是不存儲value,因此,判斷一個元素是否在set中速度很快。

set存儲的元素和dict的key類似,必須是不變對象,因此,任何可變對象是不能放入set中的。

最後,set存儲的元素也是沒有順序的。

set的這些特點,可以應用在哪些地方呢?

星期一到星期日可以用字符串'MON', 'TUE', ... 'SUN'表示。

假設我們讓用戶輸入星期一至星期日的某天,如何判斷用戶的輸入是否是一個有效的星期呢?

可以用 if 語句判斷,但這樣做非常繁瑣:

x = '???' # 用戶輸入的字符串

if x!= 'MON' and x!= 'TUE' and x!= 'WED' ... and x!='SUN':

    print 'inputerror'

else:

    print 'inputok'

注意:if 語句中的...表示沒有列出的其它星期名稱,測試時,請輸入完整。

如果事先創建好一個set,包含'MON' ~ 'SUN':

weekdays = set(['MON', 'TUE', 'WED', 'THU', 'FRI','SAT', 'SUN'])

再判斷輸入是否有效,只需要判斷該字符串是否在set中:

x = '???' # 用戶輸入的字符串

if x in weekdays:

    print 'inputok'

else:

    print 'inputerror'

這樣一來,代碼就簡單多了。

任務

月份也可以用set表示,請設計一個set並判斷用戶輸入的月份是否有效。

月份可以用字符串'Jan', 'Feb', ...表示。

?不會了怎麼辦

需要先創建一個包含所有月份的set。

參考代碼:

months = set(['Jan', 'Feb', 'Mar', 'Apr', 'May','Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])

x1 = 'Feb'

x2 = 'Sun'

if x1 in months:

    print 'x1:ok'

else:

    print 'x1:error'

if x2 in months:

    print 'x2:ok'

else:

    print 'x2:error'

6-9 Python之 遍歷set

由於 set 也是一個集合,所以,遍歷 set 和遍歷 list 類似,都可以通過 for 循環實現。

直接使用 for 循環可以遍歷 set 的元素:

>>> s = set(['Adam', 'Lisa', 'Bart'])

>>> for name in s:

...     printname

...

Lisa

Adam

Bart

注意: 觀察 for 循環在遍歷set時,元素的順序和list的順序很可能是不同的,而且不同的機器上運行的結果也可能不同。

任務

請用 for 循環遍歷如下的set,打印出 name: score 來。

s = set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])

注意到set的元素是tuple,因此 for 循環的變量被依次賦值爲tuple。

參考代碼:

s = set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])

for x in s:

    print x[0] +':', x[1]

6-10 Python之 更新set

由於set存儲的是一組不重複的無序元素,因此,更新set主要做兩件事:

一是把新的元素添加到set中,二是把已有元素從set中刪除。

添加元素時,用set的add()方法:

>>> s = set([1, 2, 3])

>>> s.add(4)

>>> print s

set([1, 2, 3, 4])

如果添加的元素已經存在於set中,add()不會報錯,但是不會加進去了:

>>> s = set([1, 2, 3])

>>> s.add(3)

>>> print s

set([1, 2, 3])

刪除set中的元素時,用set的remove()方法:

>>> s = set([1, 2, 3, 4])

>>> s.remove(4)

>>> print s

set([1, 2, 3])

如果刪除的元素不存在set中,remove()會報錯:

>>> s = set([1, 2, 3])

>>> s.remove(4)

Traceback (most recent call last):

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

KeyError: 4

所以用add()可以直接添加,而remove()前需要判斷。

任務

針對下面的set,給定一個list,對list中的每一個元素,如果在set中,就將其刪除,如果不在set中,就添加進去。

s = set(['Adam', 'Lisa', 'Paul'])

L = ['Adam', 'Lisa', 'Bart', 'Paul']

判斷元素是否在set中,使用in操作符。

參考代碼:

s = set(['Adam', 'Lisa', 'Paul'])

L = ['Adam', 'Lisa', 'Bart', 'Paul']

for name in L:

    if name ins:

       s.remove(name)

    else:

       s.add(name)

print s

7-1 Python之什麼是函數

我們知道圓的面積計算公式爲:

S = πr²

當我們知道半徑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 本身只需要寫一次,就可以多次調用。

抽象是數學中非常常見的概念。舉個例子:

計算數列的和,比如:1 + 2 + 3 + ... + 100,寫起來十分不方便,於是數學家發明了求和符號∑,可以把1 + 2 + 3 + ... + 100記作:

100

∑n

n=1

這種抽象記法非常強大,因爲我們看到∑就可以理解成求和,而不是還原成低級的加法運算。

而且,這種抽象記法是可擴展的,比如:

100

∑(n²+1)

n=1

還原成加法運算就變成了:

(1 x 1 + 1) + (2 x 2 + 1) + (3 x 3 + 1) + ... + (100 x100 + 1)

可見,藉助抽象,我們才能不關心底層的具體計算過程,而直接在更高的層次上思考問題。

寫計算機程序也是一樣,函數就是最基本的一種代碼抽象的方式。

Python不但能非常靈活地定義函數,而且本身內置了很多有用的函數,可以直接調用。

7-2 Python之調用函數

Python內置了很多有用的函數,我們可以直接調用。

要調用一個函數,需要知道函數的名稱和參數,比如求絕對值的函數 abs,它接收一個參數。

可以直接從Python的官方網站查看文檔:

http://docs.python.org/2/library/functions.html#abs

也可以在交互式命令行通過 help(abs) 查看abs函數的幫助信息。

調用 abs 函數:

>>> abs(100)

100

>>> abs(-20)

20

>>> abs(12.34)

12.34

調用函數的時候,如果傳入的參數數量不對,會報TypeError的錯誤,並且Python會明確地告訴你:abs()有且僅有1個參數,但給出了兩個:

>>> abs(1, 2)

Traceback (most recent call last):

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

TypeError: abs() takes exactly one argument (2 given)

如果傳入的參數數量是對的,但參數類型不能被函數所接受,也會報TypeError的錯誤,並且給出錯誤信息:str是錯誤的參數類型:

>>> abs('a')

Traceback (most recent call last):

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

TypeError: bad operand type for abs(): 'str'

而比較函數 cmp(x, y) 就需要兩個參數,如果 x<y,返回 -1,如果 x==y,返回 0,如果 x>y,返回 1:

>>> cmp(1, 2)

-1

>>> cmp(2, 1)

1

>>> cmp(3, 3)

0

Python內置的常用函數還包括數據類型轉換函數,比如   int()函數可以把其他數據類型轉換爲整數:

>>> int('123')

123

>>> int(12.34)

12

str()函數把其他類型轉換成 str:

>>> str(123)

'123'

>>> str(1.23)

'1.23'

任務

sum()函數接受一個list作爲參數,並返回list所有元素之和。請計算 1*1 + 2*2 + 3*3 + ... + 100*100。

首先,可以用 while 循環構造出 list。

參考代碼:

L = []

x = 1

while x <= 100:

    L.append(x *x)

    x = x + 1

print sum(L)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章