[TOC]
### list
#### list是一種有序的集合
Python內置的一種數據類型是列表:list。list是一種有序的集合,可以隨時添加和刪除其中的元素。
比如,列出班里所有同學的名字,就可以用一個`list`表示:
```
>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates
['Michael', 'Bob', 'Tracy']
```
- 變量`classmates`就是一個`list`。用`len()`函數可以獲得`list`元素的個數:
```
>>> len(classmates)
3
```
- 用索引來訪問`list`中每一個位置的元素,記得索引是從`0`開始的:
```
>>> classmates[0]
'Michael'
>>> classmates[1]
'Bob'
>>> classmates[2]
'Tracy'
>>> classmates[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
```
當索引超出了范圍時,Python會報一個`IndexError`錯誤,所以,要確保索引不要越界,記得最后一個元素的索引是`len(classmates) - 1`。
>[info] 如果要取最后一個元素,除了計算索引位置外,還可以用`-1`做索引,直接獲取最后一個元素:
```
>>> classmates[-1]
'Tracy'
```
>[info] 以此類推,可以獲取倒數第2個、倒數第3個:
```
>>> classmates[-2]
'Bob'
>>> classmates[-3]
'Michael'
>>> classmates[-4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
```
>[warning] 當然,倒數第`4`個就越界了。
#### `list`是一個可變的有序表
`list`是一個可變的有序表,所以,可以往`list`中追加元素到末尾:
```
>>> classmates.append('Adam')
>>> classmates
['Michael', 'Bob', 'Tracy', 'Adam']
```
也可以把元素插入到指定的位置,比如索引號為`1`的位置:
```
>>> classmates.insert(1, 'Jack')
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
```
- 要刪除`list`末尾的元素,用`pop()`方法:
```
>>> classmates.pop()
'Adam'
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy']
```
- 要刪除指定位置的元素,用`pop(i)`方法,其中`i`是索引位置:
```
>>> classmates.pop(1)
'Jack'
>>> classmates
['Michael', 'Bob', 'Tracy']
```
- 要把某個元素替換成別的元素,可以直接賦值給對應的索引位置:
```
>>> classmates[1] = 'Sarah'
>>> classmates
['Michael', 'Sarah', 'Tracy']
```
#### `list`里面的元素的數據類型也可以不同
`list`里面的元素的數據類型也可以不同,比如:
```
>>> L = ['Apple', 123, True]
```
- `list`元素也可以是另一個`list`,比如:
```
>>> s = ['python', 'java', ['asp', 'php'], 'scheme']
>>> len(s)
4
```
要注意`s`只有`4`個元素,其中`s[2]`又是一個`list`,如果拆開寫就更容易理解了:
```
>>> p = ['asp', 'php']
>>> s = ['python', 'java', p, 'scheme']
```
要拿到`'php'`可以寫`p[1]`或者`s[2][1]`,因此`s`可以看成是一個二維數組,類似的還有三維、四維……數組,不過很少用到。
- 如果一個`list`中一個元素也沒有,就是一個空的`list`,它的長度為0:
```
>>> L = []
>>> len(L)
0
```
### tuple
#### 不能修改的有序表
另一種有序列表叫元組:`tuple`。`tuple`和`list`非常類似,但是`tuple`一旦初始化就不能修改,比如同樣是列出同學的名字:
```
>>> classmates = ('Michael', 'Bob', 'Tracy')
```
現在,`classmates`這個`tuple`不能變了,它也沒有`append()`,`insert()`這樣的方法。其他獲取元素的方法和`list`是一樣的,你可以正常地使用`classmates[0]`,`classmates[-1]`,但不能賦值成另外的元素。
#### 不可變的`tuple`有什么意義?
>[info] 不可變的`tuple`有什么意義?因為`tuple`不可變,所以代碼更安全。如果可能,能用`tuple`代替`list`就盡量用`tuple`。
#### tuple的陷阱
>[info] tuple的陷阱:當你定義一個tuple時,在定義的時候,tuple的元素就必須被確定下來,比如:
```
>>> t = (1, 2)
>>> t
(1, 2)
```
- 如果要定義一個空的`tuple`,可以寫成`()`:
```
>>> t = ()
>>> t
()
```
- **但是,要定義一個只有`1`個元素的`tuple`,如果你這么定義:**
```
>>> t = (1)
>>> t
1
```
**定義的不是`tuple`,是`1`這個數!**這是因為括號`()`既可以表示`tuple`,又可以表示數學公式中的小括號,這就產生了歧義,因此,Python規定,這種情況下,按小括號進行計算,計算結果自然是`1`。
>[info] 所以,只有1個元素的tuple定義時必須加一個逗號,,來消除歧義:
```
>>> t = (1,)
>>> t
(1,)
```
**Python在顯示只有`1`個元素的`tuple`時,也會加一個逗號,,以免你誤解成數學計算意義上的括號。**
#### 一個“可變的”`tuple`
最后來看一個“可變的”`tuple`:
```
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
```
這個tuple定義的時候有`3`個元素,分別是`'a'`,`'b'`和一個`list`。不是說`tuple`一旦定義后就不可變了嗎?怎么后來又變了?
**別急,我們先看看定義的時候`tuple`包含的`3`個元素:**

**當我們把`list`的元素`'A'`和`'B'`修改為`'X'`和`'Y'`后,`tuple`變為:**

**表面上看,tuple的元素確實變了,但其實變的不是tuple的元素,而是list的元素。**`tuple`一開始指向的`list`并沒有改成別的`list`,所以,**`tuple`所謂的“不變”是說,`tuple`的每個元素,指向永遠不變。**即指向`'a'`,就不能改成指向`'b'`,指向一個`list`,就不能改成指向其他對象,但指向的這個`list`本身是可變的!
#### tuple “指向不變”性
>[info] 理解了“指向不變”后,要創建一個內容也不變的`tuple`怎么做?那就必須保證`tuple`的每一個元素本身也不能變。
### 練習
#### 請用索引取出下面`list`的指定元素:
```
# -*- coding: utf-8 -*-
L = [
['Apple', 'Google', 'Microsoft'],
['Java', 'Python', 'Ruby', 'PHP'],
['Adam', 'Bart', 'Lisa']
]
```
### 小結
#### `list`和`tuple`
`list`和`tuple`是Python內置的有序集合,一個可變,一個不可變。根據需要來選擇使用它們。
### 練習參考源碼
```
# -*- coding: utf-8 -*-
L = [
['Apple', 'Google', 'Microsoft'],
['Java', 'Python', 'Ruby', 'PHP'],
['Adam', 'Bart', 'Lisa']
]
# 打印Apple:
print(L[0][0])
# 打印Python:
print(L[2][1])
# 打印Lisa:
print(L[-1][-1])
```
- Python教程
- Python簡介
- 安裝Python
- Python解釋器
- 第一個 Python 程序
- 使用文本編輯器
- Python代碼運行助手
- 輸入和輸出
- 源碼
- learning.py
- Python基礎
- 數據類型和變量
- 字符串和編碼
- 使用list和tuple
- 條件判斷
- 循環
- 使用dict和set
- 函數
- 調用函數
- 定義函數
- 函數的參數
- 遞歸函數
- 高級特性
- 切片
- 迭代
- 列表生成式
- 生成器
- 迭代器
- 函數式編程
- 高階函數
- map/reduce
- filter
- sorted
- 返回函數
- 匿名函數
- 裝飾器
- 偏函數
- Python函數式編程——偏函數(來自博客)
- 模塊
- 使用模塊
- 安裝第三方模塊
- 面向對象編程
- 類和實例
- 訪問限制
- 繼承和多態
- 獲取對象信息
- 實例屬性和類屬性
- 面向對象高級編程
- 使用__slots__
- 使用@property
- 多重繼承
- 定制類
- 使用枚舉類
- 使用元類
- 錯誤、調試和測試
- 錯誤處理
- 調試
- 單元測試
- 文檔測試
- IO編程
- 文件讀寫
- StringIO和BytesIO
- 操作文件和目錄
- 序列化
- 進程和線程
- 多進程
- 多線程
- ThreadLocal
- 進程 vs. 線程
- 分布式進程
- 正則表達式
- 常用內建模塊
- datetime
- collections
- base64
- struct
- hashlib
- itertools
- contextlib
- XML
- HTMLParser
- urllib
- 常用第三方模塊
- PIL
- virtualenv
- 圖形界面
- 網絡編程
- TCP/IP簡介
- TCP編程
- UDP編程
- 電子郵件
- SMTP發送郵件
- POP3收取郵件
- 訪問數據庫
- 使用SQLite
- 使用MySQL
- 使用SQLAlchemy
- Web開發
- HTTP協議簡介
- HTML簡介
- WSGI接口
- 使用Web框架
- 使用模板
- 異步IO
- 協程
- asyncio
- async/await
- aiohttp
- 實戰
- Day 1 - 搭建開發環境
- Day 2 - 編寫Web App骨架
- Day 3 - 編寫ORM
- Day 4 - 編寫Model
- Day 5 - 編寫Web框架
- Day 6 - 編寫配置文件
- Day 7 - 編寫MVC
- Day 8 - 構建前端
- Day 9 - 編寫API
- Day 10 - 用戶注冊和登錄
- Day 11 - 編寫日志創建頁
- Day 12 - 編寫日志列表頁
- Day 13 - 提升開發效率
- Day 14 - 完成Web App
- Day 15 - 部署Web App
- Day 16 - 編寫移動App
- FAQ
- 期末總結