[TOC]
# 数据结构
> 变量只能存储1个数据,存储大量数据的容器,在Python中称为:内置数据结构(Built-in Data Structure)
日常使用的网站,移动应用,甚至手机短信都依赖数据结构来进行存储数据,其中的数据以一种特定的格式存储在数据结构中,在用户需要时被拿出来展现.
![网络中数据](https://box.kancloud.cn/6b3e8de9843f5b26b9e1e1caadab0f5c_482x484.png)
Python 有四种数据结构分别是:列表,字典,元组,集合. 每种数据结构都有自己的特点,并且有独到的用处,.整体上认识下四种数据结构
> 语法上: 列表中元素使用 `[]` 括起来, 字典和集合使用`{}` , 元组使用:`()`
> 字典是中元素是成对的,格式key:value
> set 保存的数据是唯一不重复的!
> 列表最常用,是内存中一组连续的存储空间,和字符串类似!
> 元组是数据不重复的列表
## 列表(list)
> 列表是内存中一组连续的存储空间. 列表的索引与字符串分片类似,同样是分正反两种索引方式,只要输入对应位置就能返回这个位置上的值:
![列表](https://box.kancloud.cn/cf7b6c6fff7baa6ab35033fe695b2344_567x127.png)
### 列表特点
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) ,习惯上称为: "键值对"
>没有顺序
![dict](https://box.kancloud.cn/c5f15352664afa3e4f8d6395e8ecaa56_499x338.png)
**特点**
- 字典是无序序列,所以分片无法使用
- 字典中数必须以键值对存在
- 访问 ` 变量名[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)
> 集合是高中数学中的概念! 保存一堆无序数据! 经常用于去掉重复数据.
> 每个集合中元素都是无序的,不重复的任意对象. 我们可以通过集合判断从属关系,还可以通过集合把数据结构中重复的元素减掉
![set](https://box.kancloud.cn/063b67f2cb52dec351d8a8e07e9f7c73_275x267.png)
>集合不能被切片也不能别索引,除了做集合运算之外,集合元素也可以添加和删除
```
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):
使用变量
```
![多个列表](https://box.kancloud.cn/01bea51b55558463b3f92c22b6609fd1_537x147.png)
## 推导式/列表解析式
> 数据结构的推导式(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循环表达式,虚线前面可以是我们想要放在列表中的元素,在这个案例中放在列表中的元素既是后面循环元素本身
![推导式](https://box.kancloud.cn/1af6c43209b11cea162e19a8d0b6cd16_553x83.png)
更多案例
```
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]))
```