十分鐘快速入門 Python

solocoder發表於2019-01-22

本文以 Eric Matthes 的《Python程式設計:從入門到實踐》為基礎,以有一定其他語言經驗的程式設計師視角,對書中內容提煉總結,化繁為簡,將這本書的精髓融合成一篇10分鐘能讀完的文章。

讀完本篇文章後,可對 Python 語言特性、編碼風格有一定了解,並可寫出簡單的 Python 程式。

100 多位經驗豐富的開發者參與,在 Github 上獲得了近 1000star 的開源專案想了解下嗎?
專案地址:github.com/cachecats/c…

一、安裝與執行

各個系統的 Python 安裝教程請自行查閱資料,這裡不再贅述。

檢查 Python 版本,在命令列輸入 python 即可,同時會進入命令列互動模式,可以在這裡執行 python 命令。

如果電腦中安裝了 python2.x 和 python3.x 兩個版本,輸入 python 執行的是 2.x 版本。想執行 3.x,則需輸入 python3

在命令列輸入 python

Solo-mac:~ solo$ python
Python 2.7.10 (default, Aug 17 2018, 19:45:58)
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
複製程式碼

在命令列輸入 python3

Solo-mac:~ solo$ python3
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 26 2018, 23:26:24)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
複製程式碼

輸入 exit() 即可退出命令列模式。

命令列執行 python 檔案

如果是寫好了一個 python 檔案,想通過命令列執行它,進入這個目錄,在命令列輸入 python 檔名.py 即可。

比如桌面上有個檔案 hello.py,內容是列印一句話:

print("Hello, Python")
複製程式碼

想執行它,先進入 Desktop 目錄,再在命令列輸入 python hello.py 就能執行:

Solo-mac:Desktop solo$ python hello.py
Hello, Python
複製程式碼

二、變數和簡單資料型別

2.1 變數命名規則

  • 變數名只能包含字母、數字和下劃線。變數名可以字母或下劃線打頭,但不能以數字打 頭,例如,可將變數命名為message_1,但不能將其命名為1_message。
  • 變數名不能包含空格,但可使用下劃線來分隔其中的單詞。例如,變數名greeting_message 可行,但變數名greeting message會引發錯誤。
  • 不要將Python關鍵字和函式名用作變數名,即不要使用Python保留用於特殊用途的單詞, 如print。
  • 變數名應既簡短又具有描述性。例如,name比n好,student_name比s_n好,name_length比length_of_persons_name好。
  • 慎用小寫字母l和大寫字母O,因為它們可能被人錯看成數字1和0。

變數名應該是小寫的,雖然沒有強制規定,但是約定俗稱的規則。

2.2 字串

字串就是一系列字元。在Python中,用引號括起的都是字串,其中的引號可以是單引號,也可以是雙引號,還可以同時使用。如:

"This is a string." 
'This is also a string.'
"I love 'python'"
複製程式碼

2.2.1 字串的簡單運算

下面介紹字串的簡單運算。

title()

title()以首字母大寫的方式顯示每個單詞,即將每個單詞的首字母都改為大寫。

>>> name = 'solo coder'
>>> name.title()
'Solo Coder'
複製程式碼
upper()、lower()

將字串改為全部大寫或全部小寫。

>>> name
'solo coder'
>>> name.upper()
'SOLO CODER'
>>> name.lower()
'solo coder'
>>> name
'solo coder'
複製程式碼

注意:title()、upper()、lower() 均不改變原字串,只是輸出了一個新的字串。

2.2.2 合併(拼接)字串

Python使用加號(+)來合併字串。

>>> first = 'solo'
>>> last = 'coder'
>>> full = first + ' ' + last
>>> full
'solo coder'
複製程式碼

2.2.3 使用製表符或換行符來新增空白

在程式設計中,空白泛指任何非列印字元,如空格、製表符和換行符。

要在字串中新增製表符,可使用字元組合 \t,要在字串中新增換行符,可使用字元組合 \n

>>> print('\tPython')
	Python
>>> print('Hello,\nPython')
Hello,
Python
複製程式碼

2.2.4 刪除空白

rstrip() 刪除右側空白,lstrip() 刪除左側空白,strip() 刪除兩端空白。

>>> msg = ' Python '
>>> msg
' Python '
>>> msg.rstrip()
' Python'
>>> msg.lstrip()
'Python '
>>> msg.strip()
'Python'
>>> msg
' Python '
複製程式碼

注意執行完去空格命令後,再列印出 msg,還是原來的字串,這說明 strip() 也不改變原來的字串。

2.2.5 Python 2 中的 print 語句

在Python 2中,print語句的語法稍有不同:

>>> python2.7
>>> print "Hello Python 2.7 world!" 
Hello Python 2.7 world!
複製程式碼

在Python 2中,無需將要列印的內容放在括號內。從技術上說,Python 3中的print是一個函式,因此括號必不可少。有些Python 2 print語句也包含括號,但其行為與Python 3中稍有不同。簡單地說,在Python 2程式碼中,有些print語句包含括號,有些不包含。

2.3 數字

2.3.1 整數

在Python中,可對整數執行加(+)減(-)乘(*)除(/)運算。

>>> 2 + 3 
5
>>> 3 - 2 
1
>>> 2 * 3 
6
>>> 3 / 2 
1.5
複製程式碼

Python還支援運算次序,因此你可在同一個表示式中使用多種運算。你還可以使用括號來修 改運算次序,讓Python按你指定的次序執行運算,如下所示:

>>> 2 + 3*4
14
>>> (2 + 3) * 4 20
複製程式碼

2.3.2 浮點數

Python將帶小數點的數字都稱為浮點數。大多數程式語言都使用了這個術語,它指出了這樣一個事實:小數點可出現在數字的任何位置。

從很大程度上說,使用浮點數時都無需考慮其行為。你只需輸入要使用的數字,Python通常都會按你期望的方式處理它們:

>>> 0.1 + 0.1
0.2
>>> 0.2 + 0.2 9 0.4
>>>2 * 0.1
0.2
>>>2 * 0.2
0.4
複製程式碼

但需要注意的是,結果包含的小數位數可能是不確定的:

>>> 0.2 + 0.1 
0.30000000000000004 
>>> 3 * 0.1 
0.30000000000000004
複製程式碼

所有語言都存在這種問題,沒有什麼可擔心的。Python會盡力找到一種方式,以儘可能精確地表示結果,但鑑於計算機內部表示數字的方式,這在有些情況下很難。後面將會學習更多的處理方式。

2.3.3 使用函式str()避免型別錯誤

如果用數字跟字串拼接,就會出現型別錯誤。為避免這個問題,可以使用 str() 將數字轉換為字串再進行操作。

>>> age = 18
>>> print('my age is ' + age)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
>>> print('my age is ' + str(age))
my age is 18
複製程式碼

2.3.4 Python 2 中的整數

在Python 2中,將兩個整數相除得到的結果稍有不同:

>>> python2.7 
>>> 3 / 2
1
複製程式碼

Python返回的結果為1,而不是1.5。在Python 2中,整數除法的結果只包含整數部分,小數部 分被刪除。請注意,計算整數結果時,採取的方式不是四捨五入,而是將小數部分直接刪除。

在Python 2中,若要避免這種情況,務必確保至少有一個運算元為浮點數,這樣結果也將為 浮點數:

>>> 3 / 2
1
>>> 3.0 / 2
1.5
>>> 3 / 2.0 
1.5
>>> 3.0 / 2.0 
1.5
複製程式碼

從Python 3轉而用Python 2或從Python 2轉而用Python 3時,這種除法行為常常會令人迷惑。使用或編寫同時使用浮點數和整數的程式碼時,一定要注意這種異常行為。

2.3.5 註釋

在Python中,註釋用井號(#)標識。井號後面的內容都會被Python直譯器忽略。如

# 向大家問好
print("Hello Python people!")
複製程式碼

三、列表

列表由一系列按特定順序排列的元素組成。

在Python中,用方括號([])來表示列表,並用逗號來分隔其中的元素。

>>> list = []
>>> list.append('haha')
>>> list.append('heihei')
>>> list.append('hehe')
>>> list
['haha', 'heihei', 'hehe']
>>> list[0]
'haha'
複製程式碼

獲取最後一個元素可以用 -1,如 list[-1] 是獲取最後一個元素,list[-2] 是獲取倒數第二個元素。

3.1 列表的增刪改查

3.1.1 修改元素

修改元素直接用索引修改

>>> list[0] = 'nihao'
>>> list
['nihao', 'heihei', 'hehe']
複製程式碼

3.1.2 新增元素

可以在末尾新增,也可以在任意位置插入。

在末尾新增:append

>>> list.append('wa')
>>> list
['nihao', 'heihei', 'hehe', 'wa']
複製程式碼

插入:insert

>>> list.insert(1, 'hello')
>>> list
['nihao', 'hello', 'heihei', 'hehe', 'wa']
複製程式碼

3.1.3 刪除元素

刪除有三種方式:

  • del:按索引刪除
  • pop():刪除列表最後一個元素並返回最後一個元素的值。也可以傳索引刪除任意位置的值。
  • remove():按值刪除
>>> list
['nihao', 'hello', 'heihei', 'hehe', 'wa']
>>> del list[1]
>>> list
['nihao', 'heihei', 'hehe', 'wa']
>>> list.pop()
'wa'
>>> list.remove('hehe')
>>> list
['nihao', 'heihei']
複製程式碼

pop() 傳索引刪除其他位置的值

>>> list
['nihao', 'heihei']
>>> list.pop(0)
'nihao'
>>> list
['heihei']
複製程式碼

注意:

方法remove()只刪除第一個指定的值。如果要刪除的值可能在列表中出現多次,就需要使用迴圈來判斷是否刪除了所有這樣的值。

如果你不確定該使用del語句還是pop()方法,下面是一個簡單的判斷標準:如果你要從列表中刪除一個元素,且不再以任何方式使用它,就使用del語句;如果你要在刪除元素後還能繼續使用它,就使用方法pop()。

3.2 組織列表

本節將介紹列表的排序、反轉、計算長度等操作。

列表的排序主要有兩種方式:

  • 使用方法sort()對列表進行永久性排序
  • 使用函式sorted()對列表進行臨時排序

3.2.1 使用方法sort()對列表進行永久性排序

使用 sort() 方法將改變原列表。如果要反轉排序,只需向sort()方法傳遞引數 reverse=True。

>>> list
['zhangsan', 'lisi', 'bob', 'alex']
>>> list.sort()
>>> list
['alex', 'bob', 'lisi', 'zhangsan']
>>> list.sort(reverse=True)
>>> list
['zhangsan', 'lisi', 'bob', 'alex']
複製程式碼

3.2.2 使用函式sorted()對列表進行臨時排序

函式 sorted() 讓你能夠按特定順序顯示列表元素,同時不影響它們在列表中的原始排列順序。

如果要反轉排序,只需向 sorted() 傳遞引數 reverse=True。

>>> list = ['douglas','alex','solo','super']
>>> sorted(list)
['alex', 'douglas', 'solo', 'super']
>>> list
['douglas', 'alex', 'solo', 'super']
>>> sorted(list, reverse=True)
['super', 'solo', 'douglas', 'alex']
>>> list
['douglas', 'alex', 'solo', 'super']
複製程式碼

3.2.3 反轉列表

要反轉列表元素的排列順序,可使用方法 reverse()reverse() 也會改變原始列表。

reverse() 只會按原來的順序反轉,不會進行額外的按字母排序。

>>> list
['douglas', 'alex', 'solo', 'super']
>>> list.reverse()
>>> list
['super', 'solo', 'alex', 'douglas']
複製程式碼

3.2.4 確定列表的長度

使用函式len()可快速獲悉列表的長度。

>>> list
['super', 'solo', 'alex', 'douglas']
>>> len(list)
4
複製程式碼

3.3 操作列表

3.3.1 迴圈

使用 for…in 迴圈。

python 以縮排來區分程式碼塊,所以需要正確的縮排

>>> cats
['super', 'solo', 'alex', 'douglas']
>>> for cat in cats:
...     print(cat)
...
super
solo
alex
douglas
複製程式碼

3.3.2 range()

Python函式range()讓你能夠輕鬆地生成一系列的數字。

>>> for value in range(1,5):
...     print(value)
...
1
2
3
4
複製程式碼

注意:range() 會產生包含第一個引數但不包含第二個引數的一系列數值。

使用 range() 建立列表

>>> numbers = list(range(1,6))
>>> numbers
[1, 2, 3, 4, 5]
複製程式碼

range() 還可以指定步長。下面的例子生成了從0開始,到11的偶數:

>>> nums = list(range(0,11,2))
>>> nums
[0, 2, 4, 6, 8, 10]
複製程式碼

3.3.3 對列表簡單的計算

有幾個專門用於處理數字列表的Python函式。

  • min():計算最小值
  • max():計算最大值
  • sum():計算總和
>>> numbers
[1, 2, 3, 4, 5]
>>> min(numbers)
1
>>> max(numbers)
5
>>> sum(numbers)
15
複製程式碼

3.3.4 列表解析

列表解析將for迴圈和建立新元素的程式碼合併成一行,並自動附加新元素。

>>> squares = [value**2 for value in range(1,11)]
>>> squares
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
複製程式碼

要使用這種語法,首先指定一個描述性的列表名,如squares;然後,指定一個左方括號, 並定義一個表示式,用於生成你要儲存到列表中的值。在這個示例中,表示式為 value ** 2,它計 算平方值。接下來,編寫一個for迴圈,用於給表示式提供值,再加上右方括號。在這個示例中, for迴圈為for value in range(1,11),它將值1~10提供給表示式 value ** 2。請注意,這裡的for 語句末尾沒有冒號。

3.4 切片

要建立切片,可指定要使用的第一個元素和最後一個元素的索引。與函式range()一樣,Python在到達你指定的第二個索引前面的元素後停止。要輸出列表中的前三個元素,需要指定索引0~3,這將輸出分別為0、1和2的元素。

>>> names = ['aa','bb','cc','dd']
>>> print(names[1:4])
['bb', 'cc', 'dd']
複製程式碼

如果你沒有指定第一個索引,Python將自動從列表開頭開始:

>>> print(names[:4])
['aa', 'bb', 'cc', 'dd']
複製程式碼

如果沒有指定終止索引,將自動取到列表末尾

>>> print(names[2:])
['cc', 'dd']
複製程式碼

也可以使用負數索引,比如返回最後三個元素

>>> print(names[-3:])
['bb', 'cc', 'dd']
複製程式碼

遍歷切片

>>> for name in names[1:3]:
...     print(name)
...
bb
cc
複製程式碼

3.5 複製列表

可以使用切片來快速複製列表,不指定開始索引和結束索引。

>>> names
['aa', 'bb', 'cc', 'dd']
>>> names2 = names[:]
>>> names2
['aa', 'bb', 'cc', 'dd']
複製程式碼

用切片複製出來的新列表,跟原來的列表是完全不同的列表,改變其實一個不會影響另一個列表。

>>> names.append('ee')
>>> names
['aa', 'bb', 'cc', 'dd', 'ee']
>>> names2
['aa', 'bb', 'cc', 'dd']
複製程式碼

而如果簡單的通過賦值將 names 賦值給 names2,就不能得到兩個列表,實際上它們都指向了同一個列表。如果改變其中一個,另一個也將被改變。

>>> names
['aa', 'bb', 'cc', 'dd']
>>> names2 = names
>>> names2
['aa', 'bb', 'cc', 'dd']
>>> names.append('ee')
>>> names
['aa', 'bb', 'cc', 'dd', 'ee']
>>> names2
['aa', 'bb', 'cc', 'dd', 'ee']
複製程式碼

3.6 元組

Python將不能修改的值稱為不可變的,而不可變的列表被稱為元組。

元組看起來猶如列表,但使用圓括號而不是方括號來標識。定義元組後,就可以使用索引來訪問其元素,就像訪問列表元素一樣。

>>> food = ('apple', 'orange')
>>> food[0]
'apple'
>>> food[1]
'orange'
>>> food[1] = 'banana'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
複製程式碼

遍歷用法跟列表一致。

四、條件判斷

每條if語句的核心都是一個值為True或False的表示式,這種表示式被稱為條件測試。

  • 檢查是否相等,用 ==

  • 檢查是否不相等,用 !=

  • 數字比較 ><>=<=

  • 多個條件與 and

  • 多個條件或 or

  • 判斷列表是否包含某元素 in

    >>> names
    ['aa', 'bb', 'cc', 'dd', 'ee']
    >>> 'bb' in names
    True
    複製程式碼
  • 判斷列表是否不包含某元素

    >>> names
    ['aa', 'bb', 'cc', 'dd', 'ee']
    >>> 'ff' not in names
    True
    複製程式碼

if 語句

簡單的 if-else

>>> a = 10
>>> if a > 10:
...     print('hello')
... else:
...     print('bye')
...
bye
複製程式碼

if-elif-else

>>> if a<5:
...     print(a<5)
... elif 5<a<10:
...     print('5<a<10')
... else:
...     print('a>10')
...
a>10
複製程式碼

五、字典

在Python中,字典是一系列鍵-值對。每個鍵都與一個值相關聯,你可以使用鍵來訪問與之相關聯的值。與鍵相關聯的值可以是數字、字串、列表乃至字典。事實上,可將任何Python物件用作字典中的值。

5.1 字典的增刪改查

使用字典

在Python中,字典用放在花括號{}中的一系列鍵-值對錶示。

>>> user = {'name':'bob', 'sex':'male', 'age':20}
>>> user
{'name': 'bob', 'sex': 'male', 'age': 20}
複製程式碼

訪問字典中的值

要獲取與鍵相關聯的值,可依次指定字典名和放在方括號內的鍵。

>>> user
{'name': 'bob', 'sex': 'male', 'age': 20}
>>> user['name']
'bob'
>>> user['age']
20
複製程式碼

新增鍵值對

字典是一種動態結構,可隨時在其中新增鍵—值對。

>>> user['city']='beijing'
>>> user
{'name': 'bob', 'sex': 'male', 'age': 20, 'city': 'beijing'}
複製程式碼

修改字典中的值

要修改字典中的值,可依次指定字典名、用方括號括起的鍵以及與該鍵相關聯的新值。

>>> cat = {}
>>> cat['color'] = 'white'
>>> cat['age'] = 4
>>> cat
{'color': 'white', 'age': 4}
>>> cat['age'] = 6
>>> cat
{'color': 'white', 'age': 6}
複製程式碼

刪除鍵值對

對於字典中不再需要的資訊,可使用del語句將相應的鍵—值對徹底刪除。使用del語句時,必須指定字典名和要刪除的鍵。

>>> del cat['color']
>>> cat
{'age': 6}
複製程式碼

5.2 遍歷字典

字典可用於以各種方式儲存資訊,因此有多種遍歷字典的方式:可遍歷字典的所有鍵—值對、鍵或值。

遍歷所有鍵值對 items()

>>> cat
{'age': 6, 'color': 'white', 'city': 'beijing'}
>>> for k,v in cat.items():
...     print(k + '-' + str(v))
...
age-6
color-white
city-beijing
複製程式碼

通過 for k,v in cat.items() 的方式遍歷所有的鍵值對,k 代表鍵,v 代表值。

注意:即便遍歷字典時,鍵—值對的返回順序也與儲存順序不同。Python不關心鍵—值對的儲存順序,而只跟蹤鍵和值之間的關聯關係。

遍歷所有鍵 keys()

如果不需要用值,可以用 keys() 遍歷出所有的鍵。

>>> cat
{'age': 6, 'color': 'white', 'city': 'beijing'}
>>> for k in cat.keys():
...     print(k.title())
...
Age
Color
City
複製程式碼

上面的例子列印出了 cat 的所有鍵,用字串的 title() 方法使每個單詞的首字母大寫。

遍歷字典時會預設遍歷所有的鍵,for k in cat.keys()for k in cat 的效果一樣。

按順序遍歷所有鍵,可用 sorted() 排序,這讓Python列出字典中的所有鍵,並在遍歷前對這個列表進行排序。

>>> for k in sorted(cat.keys()):
...     print(k.title())
...
Age
City
Color
複製程式碼

遍歷所有值 values()

>>> for value in cat.values():
...     print(str(value))
...
6
white
beijing
複製程式碼

如果需要剔除重複項,可以使用 set()

>>> cat
{'age': 6, 'color': 'white', 'city': 'beijing', 'city2': 'beijing'}
>>> for value in cat.values():
...     print(str(value))
...
6
white
beijing
beijing
>>> for value in set(cat.values()):
...     print(str(value))
...
beijing
white
6
複製程式碼

5.3 巢狀

可以在列表中巢狀字典、在字典中巢狀列表以及在字典中巢狀字典。這裡就不演示了。

六、使用者輸入和while迴圈

6.1 使用者輸入

函式input()讓程式暫停執行,等待使用者輸入一些文字。獲取使用者輸入後,Python將其儲存在一個變數中,以方便你使用。

>>> msg = input('Please input your name: ')
Please input your name: solo
>>> msg
'solo'
複製程式碼

如果你使用的是Python 2.7,應使用函式raw_input()來提示使用者輸入。這個函式與Python 3中的input()一樣,也將輸入解讀為字串。

Python 2.7也包含函式input(),但它將使用者輸入解讀為Python程式碼,並嘗試執行它們。如果你使用的是Python 2.7,請使用raw_input()而不是input()來獲取輸入。

如果想將輸入的內容轉換為數字,可以用 int() 來轉換。

6.2 while 迴圈

for迴圈用於針對集合中的每個元素都一個程式碼塊,而while迴圈不斷地執行,直到指定的條件不滿足為止。

>>> num = 1
>>> while num <= 5:
...     print(str(num))
...     num += 1
...
1
2
3
4
5
複製程式碼

break

要立即退出while迴圈,不再執行迴圈中餘下的程式碼,也不管條件測試的結果如何,可使用break語句。break語句用於控制程式流程,可使用它來控制哪些程式碼行將執行,哪些程式碼行不執行,從而讓程式按你的要求執行你要執行的程式碼。

continue

要返回到迴圈開頭,並根據條件測試結果決定是否繼續執行迴圈,可使用continue語句,它不像 break 語句那樣不再執行餘下的程式碼並退出整個迴圈。

七、函式

Python 用關鍵字 def 來定義函式,函式名以冒號 : 結尾,冒號之後的縮排裡的內容都是函式體。

>>> def greet():
...     print('Hello World!')
...
>>> greet()
Hello World!
複製程式碼

7.1 函式引數

可以向函式傳遞引數。下面的例子向函式 greet() 傳遞了個引數 name。其中 name 是形參,solo 是實參。

>>> def greet(name):
...     print('Hello,' + name)
...
>>> greet('solo')
Hello,solo
複製程式碼

向函式傳遞實參的方式很多,可使用位置實參,這要求實參的順序與形參的順序相同;也可使用關鍵字實參,其 中每個實參都由變數名和值組成;還可使用列表和字典。

位置實參

你呼叫函式時,Python必須將函式呼叫中的每個實參都關聯到函式定義中的一個形參。為此,最簡單的關聯方式是基於實參的順序。這種關聯方式被稱為位置實參。

>>> def student(name, age):
...     print('Hello, My name is ' + name + ', I am ' + str(age) + ' years old')
...
>>> student('solo', 18)
Hello, My name is solo, I am 18 years old
複製程式碼

按照形參定義的順序傳遞的實參就稱為位置實參。

關鍵字實參

關鍵字實參是傳遞給函式的名稱—值對。關鍵字實參讓你無需考慮函式呼叫中的實參順序,還清楚地指出了函式呼叫中各個值的用途。

>>> student(age=18, name='solo')
Hello, My name is solo, I am 18 years old
複製程式碼

接著位置實參中的例子,student(name, age) 方法第一個引數是 name,第二個引數是 age 。我們用關鍵字實參指明傳遞的是哪一個,即使順序寫亂了得到的結果也不會亂。

預設值

編寫函式時,可給每個形參指定預設值。在呼叫函式中給形參提供了實參時,Python將使用指定的實參值;否則,將使用形參的預設值。因此,給形參指定預設值後,可在函式呼叫中省略相應的實參。使用預設值可簡化函式呼叫,還可清楚地指出函式的典型用法。

>>> def student(name, age=18):
...     print('Hello, My name is ' + name + ', I am ' + str(age) + ' years old')
...
>>> student('bob')
Hello, My name is bob, I am 18 years old
>>> student('nicole')
Hello, My name is nicole, I am 18 years old
>>> student('bob', 20)
Hello, My name is bob, I am 20 years old
複製程式碼

如上,給 student() 函式定義的第二個引數 age 設定了預設值 18,如果呼叫時只傳一個引數,無論傳的是什麼 age 都是 18。當傳兩個引數時,傳遞的實參就會覆蓋掉預設值。

注意:使用預設值時,在形參列表中必須先列出沒有預設值的形參,再列出有預設值的實參。這讓Python依然能夠正確地解讀位置實參。

7.2 返回值

函式並非總是直接顯示輸出,相反,它可以處理一些資料,並返回一個或一組值。函式返回 的值被稱為返回值。在函式中,可使用return語句將值返回到呼叫函式的程式碼行。返回值讓你能夠將程式的大部分繁重工作移到函式中去完成,從而簡化主程式。

>>> def student(name):
...     return name
...
>>> name = student('solo')
>>> name
'solo'
複製程式碼

返回字典

函式可返回任何型別的值,包括列表和字典等較複雜的資料結構。例如,下面的函式接受姓名和年齡,並返回一個表示人的字典:

>>> def build_person(name,age):
...     person = {'name':name, 'age':age}
...     return person
...
>>> p = build_person('solo',18)
>>> p
{'name': 'solo', 'age': 18}
複製程式碼

7.3 傳遞任意數量的實參

有時候,你預先不知道函式需要接受多少個實參,好在Python允許函式從呼叫語句中收集任意數量的實參。

>>> def person(*args):
...     print(args)
...
>>> person('name','age','address')
('name', 'age', 'address')
複製程式碼

上面定義了一個函式 person() ,只有一個形參 *args 。形參名 *args 中的星號讓 Python 建立一個名為 args 的空元組,並將收到的所有值都封裝到這個元組中。

結合使用位置實參和任意數量實參

如果要讓函式接受不同型別的實參,必須在函式定義中將接納任意數量實參的形參放在最後。Python 先匹配位置實參和關鍵字實參,再將餘下的實參都收集到最後一個形參中。

>>> def person(city, *args):
...     print('city: ' + city + ', other args:')
...     for value in args:
...             print(value)
...
>>> person('beijing', 'name', 'age', 'tel')
city: beijing, other args:
name
age
tel
複製程式碼

函式 person() 有兩個形參,第一個 city 是普通的位置實參,第二個 *args 是可變引數。

使用任意數量的關鍵字實參

有時候,需要接受任意數量的實參,但預先不知道傳遞給函式的會是什麼樣的資訊。在這種情況下,可將函式編寫成能夠接受任意數量的鍵—值對——呼叫語句提供了多少就接受多少。一個這樣的示例是建立使用者簡介:你知道你將收到有關使用者的資訊,但不確定會是什麼樣的資訊。

def build_profile(first, last, **user_info):
	profile = {}
	profile['first_name'] = first
	profile['last_name'] = last

	for key,value in user_info.items():
		profile[key] = value

	return profile

user = build_profile('steven', 'bob', city='beijing', age=18)

print(user)
複製程式碼

執行程式碼,輸出結果是:

{'first_name': 'steven', 'last_name': 'bob', 'city': 'beijing', 'age': 18}
複製程式碼

7.4 匯入匯出

可以將函式儲存在被稱為模組的獨立檔案中,再將模組匯入到主程式中。import語句允許在當前執行的程式檔案中使用模組中的程式碼。

7.4.1 匯入整個模組

模組是副檔名為.py的檔案,包含要匯入到程式中的程式碼。

cat.py

def eat(food):
    print('I am cat, I eat ' + food)
複製程式碼

animal.py

import cat

cat.eat('fish')
複製程式碼

控制檯輸出

I am cat, I eat fish
複製程式碼

7.4.2 匯入特定的函式

你還可以匯入模組中的特定函式,這種匯入方法的語法如下:

from module_name import function_name 
複製程式碼

通過用逗號分隔函式名,可根據需要從模組中匯入任意數量的函式:

from module_name import function_0, function_1, function_2 
複製程式碼

上面的例子只匯入 cat.py 中的 eat() 方法

from cat import eat

eat('fish')
複製程式碼

得到相同的結果。

7.4.3 使用 as 給函式指定別名

如果要匯入的函式的名稱可能與程式中現有的名稱衝突,或者函式的名稱太長,可指定簡短而獨一無二的別名——函式的另一個名稱,類似於外號。要給函式指定這種特殊外號,需要在匯入它時這樣做。

from cat import eat as cat_eat

cat_eat('fish')
複製程式碼

cat.py 中的 eat() 方法匯入並指定了別名 cat_eat,使用時可以直接用別名使用。

7.4.4 使用 as 給模組指定別名

你還可以給模組指定別名。通過給模組指定簡短的別名,讓你 能夠更輕鬆地呼叫模組中的函式。

通用語法:import module_name as mn

import cat as c

c.eat('fish')
複製程式碼

7.4.5 匯入模組中的所有函式

使用星號(*)運算子可讓Python匯入模組中的所有函式:

cat.py

def eat(food):
    print('I am cat, I eat ' + food)


def run():
    print('cat run')
複製程式碼

animal.py

from cat import *

eat('fish')
run()
複製程式碼

輸出結果

I am cat, I eat fish
cat run
複製程式碼

由於匯入 了每個函式,可通過名稱來呼叫每個函式,而無需使用句點表示法。然而,使用並非自己編寫的 大型模組時,最好不要採用這種匯入方法:如果模組中有函式的名稱與你的專案中使用的名稱相 同,可能導致意想不到的結果: Python 可能遇到多個名稱相同的函式或變數,進而覆蓋函式,而 不是分別匯入所有的函式。

最佳的做法是,要麼只匯入你需要使用的函式,要麼匯入整個模組並使用句點表示法。這能 讓程式碼更清晰,更容易閱讀和理解。

7.5 函式編寫指南

  • 應給函式指定描述性名稱

  • 函式名應只包含小寫字母和下劃線

  • 每個函式都應包含簡要地闡述其功能的註釋,該註釋應緊跟在函式定義後面,並採用文件字串格式。

  • 給形參指定預設值時,等號兩邊不要有空格:

    def function_name(parameter_0, parameter_1='default value')
    複製程式碼

    對於函式呼叫中的關鍵字實參,也應遵循這種約定:

    function_name(value_0, parameter_1='value')
    複製程式碼
  • 如果程式或模組包含多個函式,可使用兩個空行將相鄰的函式分開,這樣將更容易知道前一個函式在什麼地方結束,下一個函式從什麼地方開始。

  • 所有的import語句都應放在檔案開頭,唯一例外的情形是,在檔案開頭使用了註釋來描述整個程式。

八、類

8.1 建立和使用類

class Cat():
    def __init__(self, name, color):
        self.name = name
        self.color = color

    def eat(self):
        print('cat ' + self.name + ' color ' + self.color + ', now eat')

    def run(self):
        print('cat ' + self.name + ' color ' + self.color + ', now run')


my_cat = Cat('Spring', 'white')
print(my_cat.name)
print(my_cat.color)
my_cat.eat()
my_cat.run()
複製程式碼

上面建立了類 Cat ,並例項化了 my_cat,然後呼叫了類的方法 eat()run()。輸出結果:

Spring
white
cat Spring color white, now eat
cat Spring color white, now run
複製程式碼

類中的函式稱為方法。__init__() 是函式的構造方法,每檔建立新例項時 Python 都會自動執行它。注意構造方法名字必須是這個,是規定好的。

上面的例子中__init__(self, name, color) 有三個形參,第一個形參 self 必不可少,還必須位於其他形參的前面。其他的形參可以根據需要調整。self 是一個指向例項本身的引用,讓例項能夠訪問類中的屬性和方法。

還可以通過例項直接訪問屬性:my_cat.name。但在其他語言中並不建議這樣做。

在Python 2.7中建立類

在Python 2.7中建立類時,需要做細微的修改——在括號內包含單詞object:

class ClassName(object):
複製程式碼

8.2 類的屬性

8.2.1 給屬性設定預設值

類中的每個屬性都必須有初始值,哪怕這個值是0或空字串。在有些情況下,如設定預設值時,在方法__init__() 內指定這種初始值是可行的;如果你對某個屬性這樣做了,就無需包含為它提供初始值的形參。

重新定義 Cat ,在構造方法中給屬性 age 設定預設值。

class Cat():
    def __init__(self, name, color):
        self.name = name
        self.color = color
        self.age = 3

    def eat(self):
        print('cat ' + self.name + ' color ' + self.color + ', now eat')

    def run(self):
        print('cat ' + self.name + ' color ' + self.color + ', now run')

    def print_age(self):
        print('cat`s age is ' + str(self.age))
複製程式碼

8.2.2 修改屬性的值

可以以三種不同的方式修改屬性的值:直接通過例項進行修改,通過方法進行設定。

1. 直接修改屬性的值

要修改屬性的值,最簡單的方式是通過例項直接訪問它。

class Cat():
    def __init__(self, name, color):
        self.name = name
        self.color = color
        self.age = 3

    def eat(self):
        print('cat ' + self.name + ' color ' + self.color + ', now eat')

    def run(self):
        print('cat ' + self.name + ' color ' + self.color + ', now run')

    def print_age(self):
        print('cat`s age is ' + str(self.age))


my_cat = Cat('Spring', 'white')

my_cat.print_age()
my_cat.age = 4
my_cat.print_age()
複製程式碼

輸出結果為

cat`s age is 3
cat`s age is 4
複製程式碼

上例直接通過 my_cat.age = 4 修改了 age 屬性的值。

2. 通過方法修改屬性的值

再來更新程式碼,加入 update_age() 方法來修改 age 的屬性。

class Cat():
    def __init__(self, name, color):
        self.name = name
        self.color = color
        self.age = 3

    def eat(self):
        print('cat ' + self.name + ' color ' + self.color + ', now eat')

    def run(self):
        print('cat ' + self.name + ' color ' + self.color + ', now run')

    def print_age(self):
        print('cat`s age is ' + str(self.age))

    def update_age(self, age):
        self.age = age


my_cat = Cat('Spring', 'white')
my_cat.print_age()
my_cat.update_age(10)
my_cat.print_age()
複製程式碼

執行程式碼輸出:

cat`s age is 3
cat`s age is 10
複製程式碼

8.3 繼承

一個類繼承另一個類時,它將自動獲得另一個類的所有屬性和方法;原有的類稱為父類,而新類稱為子類。子類繼承了其父類的所有屬性和方法,同時還可以定義自己的屬性和方法。

class Animal():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print('Animal ' + self.name + ' run')


class Cat(Animal):
    def __init__(self, name, age):
        super().__init__(name, age)


cat = Cat('Tony', 2)
cat.run()
複製程式碼

執行程式,輸出:

Animal Tony run
複製程式碼

先定義了類 Animal,又定義了 Cat 繼承自 AnimalAnimal稱為父類, Cat 稱為子類。通過輸出可以驗證,子類繼承了父類的方法。

在子類的構造方法中要先實現父類的構造方法:super().__init__(name, age)

還可以給子類定義自己的方法,或者重寫父類的方法。

class Animal():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print('Animal ' + self.name + ' run')


class Cat(Animal):
    def __init__(self, name, age):
        super().__init__(name, age)

    def play(self):
        print('Cat ' + self.name + ' play')

    def run(self):
        print('Cat ' + self.name + ' run')


cat = Cat('Tony', 2)
cat.run()
cat.play()
複製程式碼

我們來修改下程式,Animal 類不變,Cat 類還是繼承了 Animal ,但定義了自己的方法 play() 並重寫了父類方法 run() 。執行程式,得到輸出:

Cat Tony run
Cat Tony play
複製程式碼

Python2.7 中的繼承

在Python 2.7中,繼承語法稍有不同,ElectricCar類的定義類似於下面這樣:

class Car(object):
	def __init__(self, make, model, year):
    	--snip--
    
class ElectricCar(Car):
	def __init__(self, make, model, year):
		super(ElectricCar, self).__init__(make, model, year)
		--snip--
複製程式碼

函式super()需要兩個實參:子類名和物件self。為幫助Python將父類和子類關聯起來,這些實參必不可少。另外,在Python 2.7中使用繼承時,務必在定義父類時在括號內指定object。

8.4 匯入類

當一個檔案過長時,可以將其中一部分程式碼抽離出去,然後匯入到主檔案中。

匯入方式有多種:

  • 匯入單個類

    假如 car.py 裡定義了類 Car

    from car import Car
    複製程式碼
  • 從一個模組中匯入多個類

    假如 car.py 包含了三個類 CarBatteryElectricCar

    只匯入一個類:

    from car import ElectricCar
    複製程式碼

    匯入多個類,中間用逗號隔開:

    from car import Car, ElectricCar
    複製程式碼
  • 匯入整個模組

    還可以匯入整個模組,再使用句點表示法訪問需要的類。這種匯入方法很簡單,程式碼也易於閱讀。由於建立類例項的程式碼都包含模組名,因此不會與當前檔案使用的任何名稱發生衝突。

    import car
    my_car = car.Car()
    複製程式碼
  • 匯入模組中的所有類

    要匯入模組中的每個類,可使用下面的語法:

    from module_name import *
    複製程式碼

    不推薦使用這種匯入方式,其原因有二。

    首先,如果只要看一下檔案開頭的import語句,就 能清楚地知道程式使用了哪些類,將大有裨益;但這種匯入方式沒有明確地指出你使用了模組中 的哪些類。這種匯入方式還可能引發名稱方面的困惑。如果你不小心匯入了一個與程式檔案中其 他東西同名的類,將引發難以診斷的錯誤。這裡之所以介紹這種匯入方式,是因為雖然不推薦使 用這種方式,但你可能會在別人編寫的程式碼中見到它。

    需要從一個模組中匯入很多類時,最好匯入整個模組,並使用module_name.class_name語法 來訪問類。這樣做時,雖然檔案開頭並沒有列出用到的所有類,但你清楚地知道在程式的哪些地 方使用了匯入的模組;你還避免了匯入模組中的每個類可能引發的名稱衝突。

九、檔案和異常

9.1 從檔案中讀取資料

要使用文字檔案中的資訊,首先需要將資訊讀取到記憶體中。為此,你可以一次性讀取檔案的全部內容,也可以以每次一行的方式逐步讀取。

9.1.1 讀取整個檔案

with open('test.txt') as file_obj:
    contents = file_obj.read()
    print(contents)
複製程式碼

open() 用於開啟一個檔案,引數為檔案的路徑。

關鍵字 with 在不再需要訪問檔案後將其關閉。有了 with 你只管開啟檔案,並在需要時使用它,Python自會 在合適的時候自動將其關閉。

相比於原始檔案,該輸出唯一不同的地方是末尾多了一個空行。為何會多出這個空行呢?因為 read() 到達檔案末尾時返回一個空字串,而將這個空字串顯示出來時就是一個空行。要刪除多出來的空行,可在print語句中使用 rstrip()

檔案路徑可以是相對路徑,也可以是絕對路徑。

9.1.2 逐行讀取

with open('test.txt') as file_obj:
    for line in file_obj:
        print(line.rstrip())
複製程式碼

要以每次一行的方式檢查檔案,可對檔案物件使用for迴圈。

9.2 寫入檔案

with open('test.txt', 'w') as file_obj:
    file_obj.write("I love python")
複製程式碼

在這個示例中,呼叫open()時提供了兩個實參,第一個實參也是要開啟的檔案的名稱;第二個實參('w')告訴Python,我們要以寫入模式開啟這個檔案。

可選模式:

  • r :只讀。
  • w : 只寫。如果檔案不存在則建立,如果檔案存在則先清空,再寫入。
  • a :附加模式,寫入的內容追加到原始檔案後面。如果檔案不存在則建立。
  • r+ :可讀可寫。

如果你省略了模式實參,Python將以預設的只讀模式開啟檔案。

9.3 異常

異常是使用try-except程式碼塊處理的。try-except程式碼塊讓Python執行指定的操作,同時告訴Python發生異常時怎麼辦。

try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")
複製程式碼

else 程式碼塊

try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")
else:
	print("no exception")
複製程式碼

如果 try 中的程式碼執行成功,沒有出現異常,則執行 else 程式碼塊中的程式碼。

9.4 用 json 儲存資料

Python 中使用 json.dump()json.load() 來儲存和讀取 json 檔案。

import json

userInfo = {'username': 'jack', 'age': 18}

with open('test.txt', 'w') as obj:
    json.dump(userInfo, obj)


with open('test.txt') as obj:
    content = json.load(obj)
    print(content)
複製程式碼

上例中用 json.dump() 把資料存入到了 test.txt 中,又用 json.load() 把資料從檔案中取出並列印。

注意使用前先匯入 json 模組。

十、單元測試

先定義一個拼接名字的函式 name_function.py

def get_formatted_name(first, last):
    full_name = first + ' ' + last
    return full_name.title()
複製程式碼

再寫測試類來測試這個函式

import unittest
from name_function import get_formatted_name


class NamesTestCase(unittest.TestCase):

    def test_name_function(self):
        full_name = get_formatted_name('david', 'alex')
        self.assertEqual(full_name, 'David Alex')


unittest.main()
複製程式碼

測試類要繼承 unittest.TestCase ,通過 self.assertEqual 斷言是否得到的結果和預期相等。

常見的斷言方法

方法 用途
assertEqual(a, b) 核實a == b
assertNotEqual(a, b) 核實a != b
assertTrue(x) 核實x為True
assertFalse(x) 核實x為False
assertIn(item, list) 核實item在list中
assertNotIn(item, list) 核實item不在list中

setUp() 方法

如果你在TestCase類中包含了方法 setUp() ,Python將先執行它,再執行各個以test_打頭的方法。

通常用於做一些初始化操作。


全棧全平臺開源專案 CodeRiver

CodeRiver 是一個免費的專案協作平臺,願景是打通 IT 產業上下游,無論你是產品經理、設計師、程式設計師或是測試,還是其他行業人員,只要有好的創意、想法,都可以來 CodeRiver 免費釋出專案,召集志同道合的隊友一起將夢想變為現實!

CodeRiver 本身還是一個大型開源專案,致力於打造全棧全平臺企業級精品開源專案。涵蓋了 React、Vue、Angular、小程式、ReactNative、Android、Flutter、Java、Node 等幾乎所有主流技術棧,主打程式碼質量。

目前已經有近 100 名優秀開發者參與,github 上的 star 數量將近 1000 個。每個技術棧都有多位經驗豐富的大佬坐鎮,更有兩位架構師指導專案架構。無論你想學什麼語言處於什麼技術水平,相信都能在這裡學有所獲。

通過 高質量原始碼 + 部落格 + 視訊,幫助每一位開發者快速成長。

專案地址:github.com/cachecats/c…


您的鼓勵是我們前行最大的動力,歡迎點贊,歡迎送小星星✨ ~

十分鐘快速入門 Python

相關文章