[TOC]
# 數據結構
> 變量只能存儲1個數據,存儲大量數據的容器,在Python中稱為:內置數據結構(Built-in Data Structure)
日常使用的網站,移動應用,甚至手機短信都依賴數據結構來進行存儲數據,其中的數據以一種特定的格式存儲在數據結構中,在用戶需要時被拿出來展現.

Python 有四種數據結構分別是:列表,字典,元組,集合. 每種數據結構都有自己的特點,并且有獨到的用處,.整體上認識下四種數據結構
> 語法上: 列表中元素使用 `[]` 括起來, 字典和集合使用`{}` , 元組使用:`()`
> 字典是中元素是成對的,格式key:value
> set 保存的數據是唯一不重復的!
> 列表最常用,是內存中一組連續的存儲空間,和字符串類似!
> 元組是數據不重復的列表
## 列表(list)
> 列表是內存中一組連續的存儲空間. 列表的索引與字符串分片類似,同樣是分正反兩種索引方式,只要輸入對應位置就能返回這個位置上的值:

### 列表特點
1. 列表是內存中一組連續的存儲空間,
2. 有序!索引值分正反兩種索引, 從左到右第一個是0, 從右到左第一個是-1
3. 可存儲任意類型數據
4. 列表是可修改的序列(每個值可被修改)
5. len(列表)獲取長度
6. 不可通過索引新增數據
### 創建和訪問
> `變量名=[] ` #可先定義后賦值
> ` 變量名= [值1,值2,值3,.....]` #定義同時賦值
> `print(變量名[索引]);`
> `del 列表變量[索引] ` 刪除列表元素
```
# 列表可存儲任意類型數據
all_in_list =[
1, #整數
1.0, #小數
'a word', #字符串
print(1), #函數
True, #布爾
[1,2], #列表套列表
(1,2), #元組
{'key':'value'} #字典
]
weekDay = ['周一','周二','周三','周四','周五','周六']
print(weekDay[0])
weekDay[0]='Monday'
weekDay = ['周一','周二','周三','周四','周五','周六']
weekDay[6]='周末'; #錯誤
```
### 列表常用操作
> 根據索引找值, 修改,分片, 列表相加,列表相乘,額 成員檢測,最大最小值,長度計算,求和
```
nums1= [1,3,5,10];
nums2= [2,4,6];
print(nums1[0]) # 第一個
print(nums1[-1]) # 最后一個
print(len(nums1)) # 長度
nums1[0]=10; #修改
print(nums1+nums2) #相加
print(nums1*2) #相乘
print(nums1*2) #相乘
print(1 in nums1) #成員檢測
print(len(nums1))
print('出現次數:',nums1.count(10))
print('和:',sum(nums1))
print('分片',nums1[:]) #分片,獲取所有數據
print('分片',nums1[1:3]) #包頭不包尾
print('分片',nums1[1:]) #開始位置到最后
print('分片',nums1[:3]) #結束位置之前,不包含結束位置
print('分片',nums1[0:3:1]) #開始到結束,不包含結束位置,并且獲取數據時索引每次+跳步值來說獲取,默認跳步值為1
```
### 列表相關方法
> Python內建函數/方法
| 序號 | 函數 |
| --- | --- |
| 1 | cmp(list1,list2) 比較兩個列表元素 |
| 2 | len(list) 比較兩個列表元素 |
| 3 | max(list) 最大值 |
| 4 | min(list) 最小值 |
| 5 | list(序列/seq) 將元組轉換為列表 |
> 列表自帶方法(重點: 增加,修改,刪除)
| 序號 | 函數 |
| --- | --- |
| 1 | list.append(obj) 列表結尾增加新對象 |
| 2 | list.count(obj) 統計列表中某個元素出現的次數 |
| 3 | list.extend(seq) 列表尾部一次增加另一個序列的多個值 |
| 4 | list.index(obj) 查找元素第一次的位置 |
| 5 | list.insert(index,obj) 將對象插入列表 |
| 6 | list.pop(obj=list[-1]) 移除一個元素(默認最后一個),并返回該元素值 |
| 7 | list.remove(obj) 移除列表中某個值的第一個匹配項 |
| 8 | liset.reserve() 反向列表元素 |
| 9 | liset.sort([func]) 列表排序,可接收自定義的排序方法 |
| 10 | copy(list) 復制原有列表 |
### 列表編列
> for...in 和 while 都可以循環編列列表
**for **
```
for i in nums2:
print('值',i)
```
**while**
```
i= 0
while i< len(nums2):
print(nums2[i])
i +=1
```
**列表嵌套循環**
> 列表 = [[值1,值2], [值1,值2],.....]
> 格式 fro 編列1,編列2 in
```
users = [['張三','20'],['李四','30']]
for name,age in users:
print(name+',年齡:'+age)
```
### 練習
1. 控制臺輸入5個同學分數,計算平均分
2. 循環錄入5個學員成績,進行升序排列并輸出
3. 有一個數列,8,4,1,23,344,12, 循環輸出每個值,求所有數字和! 猜數游戲:從鍵盤中任意輸入一個數字,判斷數列是否包含在內
4. 從鍵盤輸入5個同學語文的成績,求考試最高分
5. 使用列表嵌套保存3個學員的名字,班級,和語文成績!并循環展示
## 元組(tuple)
>
> 元組是不可變的列表(穩固版的列表)!! 元組不具備修改功能!
> (元組就是一種特殊格式列表而已, 列表是鉛筆寫的有序內容,元組就是鋼筆寫的有序內容)
**創建**
> 變量 = () 或變量=(值1,值2,值3,....)
```
weekday =('周一','周二','周三','周四')
print(weekday.count('周一'))
print(weekday.index('周二'))
print(weekday[2])
```
**特點**
1. 有序集合
2. 可以存儲任意類型數據
3. 值不可變
**支持常用操作**
> 索引,分片, 序列相加,序列相乘, 成員檢測
**常用方法**
>元組特有方法2個
```
print(weekday.count('周一'))
print(weekday.index('周二'))
```
> python內置操作方法
| 序號 | 函數 |
| --- | --- |
| 1 | cmp(list1,list2) 比較兩個列表元素 |
| 2 | len(list) 比較兩個列表元素 |
| 3 | max(list) 最大值 |
| 4 | min(list) 最小值 |
| 5 | tuple(序列/seq) 將元組轉換為元組 |
**編列方式for 或 while 和list相同**
```
i= 0
while i< len(weekday):
print(weekday[i])
i +=1
```
**多層編列**
```
for 變量1, 變量2 in 元組:
使用變量
```
## 字典(dict)
>字典概念源于生活,專門用于存儲生活中成對的數據,使用名字-內中的結構存儲數據, 在Python中對應:
>鍵(key) - 值(value) ,習慣上稱為: "鍵值對"
>沒有順序

**特點**
- 字典是無序序列,所以分片無法使用
- 字典中數必須以鍵值對存在
- 訪問 ` 變量名[key]`
- 鍵不能重復,值可重復
- key類型不可修改,value可為任意對象,可修改
### 創建字典
```
dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
```
1. 空字典
```
# `變量={} ` 或 `變量= dict()`
zidian = {}
zidian =dict()
```
2. 有數據字典
```
#變量= {鍵: 值, 鍵:值, 鍵:值,.....}
url ={'百度':'baidu.com', 'QQ':'qq.com'' }
#變量=dict({key:value,key:value,.....})
url =dict({'百度':'baidu.com', 'QQ':'qq.com'' })
#變量=dict(key=值,key=值)
#變量=dict([{k:v},{k:v}......])
#變量=dict([(k:v),(k:v),(k:v),])
#變量=dict(zip((key1,key2,key3....),(value1,value2,value3......)))
```
### 常用操作
> 訪問,增加1個,增加多個,刪除某個,判斷是否存在
```
url = {'baidu':'baidu.com','qq':'qq.com','ali':'ali.com'}
print(url['baidu']) #訪問
url['youku']= 'youku.com' #增加
del url['youku'] #刪除
print('baidu' in url ) #檢測數據是否在字典鍵中
```
### 遍歷
1. 遍歷建值
```
#編列
for k,v in url.items():
print("名字:",k+"--值:"+v)
```
2. 遍歷鍵
```
#編列
for k in url.keys():
print("名字:",k)
```
3. 遍歷值
```
#編列
for v in url.values():
print("名字:",v)
```
### 常用方法
> Python內置
| 序號 | 函數 |
| --- | --- |
| 1 | cmp(dict1,dict2) 比較兩個字典元素 |
| 2 | len(dict) 長度 |
| 3 | max(dict) 最大值,默認比較key |
| 4 | min(dict) 最小值,默認比較key |
| 5 | str(dict) 轉換為字符串輸出 |
| 6 | type(變量) 判斷類型 |
> 字典內置方法/函數
| 序號 | 函數 |
| --- | --- |
| 1 | 字典.clear() 清空 |
| 2 | 字典.copy() 拷貝 |
| 3 | 字典.formkeys() 創建新字典,鍵值都為key |
| 4 | 字典.get(key,default=Node) 查找指定key的值,找不到返回默認值 |
| 5 | 字典.set(key,default=Node) 和get類似,如果key不存在就設置為默認值 |
| 6 | 字典.has_key(key) 是否包含key |
| 7 | 字典.copy() 拷貝 |
| 8 | 字典.item() 以列表返回每一項(鍵,值),實際上是一個元組 |
| 9 | 字典.keys() 返回所有的鍵 |
| 10 | 字典.values() 返回所有的值 |
| 11 | 字典.update(字典/鍵值對) 一次更新多個字典 |
| 12 | 字典.setdefault(key,值) 設置不存在的key的值 |
#### 訪問字典里的值
把相應的鍵放入熟悉的方括弧,如下實例:
```
dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'};
print "dict['Name']: ", dict['Name'];
print "dict['Age']: ", dict['Age'];
以上實例輸出結果:
dict['Name']: Zara
dict['Age']: 7
```
如果用字典里沒有的鍵訪問數據,會輸出錯誤如下:
```
dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'};
print "dict['Alice']: ", dict['Alice'];
以上實例輸出結果:
dict['Zara']:
Traceback (most recent call last):
File "test.py", line 4, in <module>
print "dict['Alice']: ", dict['Alice'];
KeyError: 'Alice'
````
#### 修改字典
向字典添加新內容的方法是增加新的鍵/值對,修改或刪除已有鍵/值對如下實例:
```
dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'};
dict['Age'] = 8; # update existing entry
dict['School'] = "DPS School"; # Add new entry
print "dict['Age']: ", dict['Age'];
print "dict['School']: ", dict['School'];
以上實例輸出結果:
dict['Age']: 8
dict['School']: DPS School
````
#### 刪除字典元素
能刪單一的元素也能清空字典,清空只需一項操作。
顯示刪除一個字典用del命令,如下實例:
```
dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'};
del dict['Name']; # 刪除鍵是'Name'的條目
dict.clear(); # 清空詞典所有條目
del dict ; # 刪除詞典
print "dict['Age']: ", dict['Age'];
print "dict['School']: ", dict['School'];
````
但這會引發一個異常,因為用del后字典不再存在:
```
dict['Age']:
Traceback (most recent call last):
File "test.py", line 8, in <module>
print "dict['Age']: ", dict['Age'];
TypeError: 'type' object is unsubscriptable
注:del()方法后面也會討論。
````
刪除字典元素
字典鍵的特性
字典值可以沒有限制地取任何python對象,既可以是標準的對象,也可以是用戶定義的,但鍵不行。
兩個重要的點需要記住:
1)不允許同一個鍵出現兩次。創建時如果同一個鍵被賦值兩次,后一個值會被記住,如下實例:
```
dict = {'Name': 'Zara', 'Age': 7, 'Name': 'Manni'};
print "dict['Name']: ", dict['Name'];
以上實例輸出結果:
dict['Name']: Manni
```
2)鍵必須不可變,所以可以用數,字符串或元組充當,所以用列表就不行,如下實例:
````
dict = {['Name']: 'Zara', 'Age': 7};
print "dict['Name']: ", dict['Name'];
以上實例輸出結果:
Traceback (most recent call last):
File "test.py", line 3, in <module>
dict = {['Name']: 'Zara', 'Age': 7};
TypeError: list objects are unhashable
````
## 集合(Set)
> 集合是高中數學中的概念! 保存一堆無序數據! 經常用于去掉重復數據.
> 每個集合中元素都是無序的,不重復的任意對象. 我們可以通過集合判斷從屬關系,還可以通過集合把數據結構中重復的元素減掉

>集合不能被切片也不能別索引,除了做集合運算之外,集合元素也可以添加和刪除
```
a_set = {1,2,3,4} #創建
a_set = add(5); #增加
a_set.discard(5) #刪除
```
### 定義和使用
```
變量 = set();
變量 = {值1,值2,......}
#注意集合內部元素是絕對唯一的,所以集合中多個相同數據只會保留一份!
```
### 集合特點
1. 集合是一種無序數據類型,無法通過索引和分片進行操作
2. 集合內部元素是唯一的,經常用于去掉重復數據
### 常用操作
**成員檢測**
```
數據 in/not in 集合 # 檢測數據在集合中是否存在
```
**編列**
````
集合 = {值1,值2,值3....}
for 變量 in 集合:
使用變量
````
**帶元組的集合遍歷**
````
集合 = {(值1,值2......),()}}
for 變量1, 變量2 in 集合:
使用變量
````
### 常用函數
> Python內置
| 序號 | 函數 |
| --- | --- |
| 1 | len(set) 長度|
| 2 | max(set) 最大值 |
| 3 | min(set) 最小值 |
| 4 | str(dict) 轉換為字符串輸出 |
| 5 | set(seq) 其他序列變為集合 |
> 集合內置方法:重點增加,刪除
| 序號 | 函數 |
| --- | --- |
| 1 | 集合.add(數據) 增加 |
| 2 | 集合.clear() 清空 |
| 3 | 集合.copy() 拷貝 |
| 4 | 集合.remove(值) 刪除指定值,改變原有集合,如果要刪的值不存在,報錯|
| 5 | 集合.discard(值) 移除指定值,改變原有集合,不存在不做任何操作 |
| 5 | 集合.pop() 隨機移除元素 |
| 5 | 集合1.intersection(集合2) 交集 |
| 5 | 集合1.difference(集合2) 差集 |
| 5 | 集合1.dunion(集合2) 并集 |
| 5 | 集合1.issubseet(集合2) 檢測是否為子集返回布爾 |
| 5 | 集合1.issuperset(集合2) 是否為超集 |
| 5 | 集合1.difference_update(集合2) 無返回值, 差集,計算結果賦值給集合1 |
| 5 | 集合1.intersection_update(集合2) 無返回值, 交集,計算結果賦值給集合1 |
| 5 | 集合1.update(集合2) 無返回結果, 并集,計算結果賦值給集合1 |
### 冰凍集合/固定集合 frozenset
>冰凍集合就是不可以進行任何修改相關操作的集合!,
**創建**
> `變量= frozenset()`
> `變量= frozenset(一個序列)`
冰凍集合的操作相關函數和方法和普通集合一樣! 只是不可以使用修改相關的方法.
注意: frozenset和普通集合一樣無本質區別,能夠使用的函數數量不一樣.僅此而已
# 數據結構一些特點
> 常用的數據結構操作技巧,工作中需要熟悉,特此說明
1. `sorted(列表)`排序,按照長短,大小,英文字母順序給每個元素排序.函數不會改變列表本身,可以理解為先將列表進行復制,然后進行排序.
2. `sorted(列表,reverse=True)` 逆向排序
## 排序
```
num_list = [6,4,6,1,2,67]
print( sorted(num_list ) ) #排序
```
## 循環多個列表
>在整理列表時如果需要兩個列表怎么辦? 可以使用 zip 函數
```
for a, b in zip(num, str):
使用變量
```

## 推導式/列表解析式
> 數據結構的推導式(List comprehension),另一個名字也叫"列表解析式", 使用方便,執行效率遠遠高于for循環
```
#for 和推導式循環數據對比
#推導式
import time
a =[]
t0 = time.clock()
for i in range(1,20000):
a.append(i)
print(time.clock()- t0,'s ')
t0 = time.clock()
b = [i for i in range(1,20000)]
print(time.clock()-t0,'s')
```
推導式用法: 可以簡單看成兩部分,紅色虛線后面使我們數學的for循環表達式,虛線前面可以是我們想要放在列表中的元素,在這個案例中放在列表中的元素既是后面循環元素本身

更多案例
```
a = [i**2 for i in range(1,10)]
print(a)
c = [j+1 for j in range(1,10)]
k = [n for n in range(1,10) if n %2 ==0]
z= [letter.lower() for letter in 'ABCDEFG']
#字典推導式略不同,因為字典結構k-v
d= { i:i+1 for i in range(4)}
e= {i:j for i,j in zip(range(1,6),'abcde')}
f = {i:j.upper() for i,j in zip(range(1,6),'abcde')}
```
## 循環時獲取元素索引
> 列表是有序的,可以使用Python中 獨有的函數 enumerate(枚舉) 來進行
```
letter = ['a','b','c','d','e']
for num, letter in enumerate(letter):
print(letter ,'is',num)
```
# 項目:文章詞頻統計
文章詞頻統計
1. 標點符號不應該被統計
2. 單詞不能被統計多次
3. python 大小寫敏感,開頭大寫的不能單獨統計
[文章下載](https://pan.baidu.com/s/1P6Fr4DAuyhyBUdS8QaRaZg) 密碼:2tp3
```
import string
path = 'Walden.txt'
#簡單統計
with open(path, 'r',encoding='utf-8') as text:
words = text.read().splite()
for word in words:
print('{}---{}次'.format(word,words.count(word)))
#排重和符號
with open(path, 'r',encoding='utf-8') as text:
words = [raw_word.strip(string.punctuation).lower() for raw_word in text.read().split()]
words_index = set(words)
counts_dict = {w:words.count(w) for w in words_index}
for word in sorted(counts_dict,key=lambda x: counts_dict[x],reverse=True):
print('{}----{} 次'.format(word, counts_dict[word]))
```