[TOC]
# dict字典{}
**无序的对象集合**
其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢
~~~
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95
~~~
为什么dict查找速度这么快?因为dict的实现原理和查字典是一样的。假设字典包含了1万个汉字,我们要查某一个字,一个办法是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法就是在list中查找元素的方法,list越大,查找越慢。
第二种方法是先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。
dict就是第二种实现方式,给定一个名字,比如'Michael',dict在内部就可以直接计算出Michael对应的存放成绩的“页码”,也就是95这个数字存放的内存地址,直接取出来,所以速度非常快。
key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value
## 增
把数据放入dict的方法,除了初始化时指定外,还可以通过key放入:
~~~
>>> d['Adam'] = 67
>>> d['Adam']
67
~~~
**setdefault()方法**
此方法是根据函数对字典进行增添元素,参数为(‘key’,‘value’) value默认为none
与直接用 dict[key] = value 的添加元素方法不同,用setdefault(key,value)方法的时候,如果字典没有该key的时候,则会正常添加,如果已经有了该key,那么将不进行操作(不会覆盖原来的值)
~~~
dic = {'name': 'jdxia', 'age': 17}
dic.setdefault('name', 'x')
dic.setdefault('a', 'b')
print(dic) # {'name': 'jdxia', 'age': 17, 'a': 'b'}
~~~
## 改
由于一个key只能对应一个value,多次对一个key放入value,后面的值会把前面的值冲掉
~~~
>>> d['Jack'] = 90
>>> d['Jack']
90
~~~
~~~
>>> d['Jack'] = 88
>>> d['Jack']
88
~~~
如果key不存在,dict就会报错:
~~~
>>> d['Thomas']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Thomas'
~~~
**update({key:value})方法**
该方法是用来追加、拓展原字典元素。
参数必须为一个字典,如下:
~~~
dic = {'name': 'jdxia', 'age': 17}
dic.update({'addr': 'a'})
~~~
如果传入的字典里有部分key与原字典相同,则该key所对应的值会被覆盖,其他没有的key则会被添加
## 查
要避免key不存在的错误,有两种办法
**一是通过in判断key是否存在**
~~~
>>> 'Thomas' in d
False
~~~
**二是通过dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value**
~~~
>>> d.get('Thomas')
>>> d.get('Thomas', -1)
-1
~~~
注意:返回None的时候Python的交互环境不显示结果
**len()测量字典中,键值对的个数**
![](https://box.kancloud.cn/3669ede2dc7b953e61abdd45af3a9ddb_331x51.png)
**keys返回一个包含字典所有KEY的列表**
![](https://box.kancloud.cn/63b81c335c8d6b379111bbdfed71fa99_331x57.png)
**values返回一个包含字典所有value的列表**
![](https://box.kancloud.cn/0fc145aeee034ed32eb72de358292881_334x57.png)
**items返回一个包含所有(键,值)元祖的列表**
![](https://box.kancloud.cn/561aadfd6dd7fca2af3d1497dc89e644_335x57.png)
**has_key dict.has_key(key)如果key在字典中,返回True,否则返回False**
![](https://box.kancloud.cn/ac4ea57630a237bf11d0a9a729f2c732_334x87.png)
## 删
**pop(key)**
与列表的pop()方法不同,字典的pop()方法必须得给它传一个key值,如果字典里没有该key,则会报错。
也可以用 pop(key,'返回值') 来指定返回值,此时,当找不到key的时候,则不会报错,会将指定的返回值返回
删除一个key,用pop(key)方法,对应的value也会从dict中删除
~~~
>>> d.pop('Bob')
75
>>> d
{'Michael': 95, 'Tracy': 85}
~~~
popitem()方法:
此方法类似于列表的pop()方法,用来随机删除一个元素,返回删除的那个元素的(健,值)
**del**
删除指定的元素
~~~
info = {'name':'班长', 'sex':'f', 'address':'地球亚洲中国北京'}
print('删除前,%s'%info['name'])
del info['name']
print('删除后,%s'%info['name'])
~~~
删除整个字典
~~~
info = {'name':'monitor', 'sex':'f', 'address':'China'}
print('删除前,%s'%info)
del info
print('删除后,%s'%info)
~~~
**clear清空整个字典**
~~~
info = {'name':'monitor', 'sex':'f', 'address':'China'}
print('清空前,%s'%info)
info.clear()
print('清空后,%s'%info)
~~~
## 遍历
![](https://box.kancloud.cn/3a84f9d86be53ff928aec77a536039e2_376x783.png)
~~~
d = {'a': '1', 'b': '2', 'c': '3'}
for k, v in d.items():
# 这种拼接要2边都是字符串
s = k + '---' + v
print(s)
~~~
## 注意
**dict内部存放的顺序和key放入的顺序是没有关系的**
和list比较,dict有以下几个特点:
1. 查找和插入的速度极快,不会随着key的增加而变慢;
2. 需要占用大量的内存,内存浪费多。
而list相反:
1. 查找和插入的时间随着元素的增加而增加;
2. 占用空间小,浪费内存很少。
所以,dict是用空间来换取时间的一种方法。
dict可以用在需要高速查找的很多地方,需要牢记的第一条就是**dict的key必须是不可变对象**
这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。
要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而**list是可变的,就不能作为key**:
~~~
>>> key = [1, 2, 3]
>>> d[key] = 'a list'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
~~~
# set集合{}
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
## 增
**创建一个set**
~~~
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}
~~~
注意,传入的参数`[1, 2, 3]`是一个list,而显示的`{1, 2, 3}`只是告诉你这个set内部有1,2,3这3个元素,显示的顺序也不表示set是有序的。。
重复元素在set中自动被过滤:
~~~
>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
{1, 2, 3}
~~~
~~~
set1 = set({1,2,3,4,5})
set2 = {1,2,3,4,5}
set3 = set('abc')
print(set1,set2,set3) #{1, 2, 3, 4, 5} {1, 2, 3, 4, 5} {'c', 'b', 'a'}
~~~
~~~
info = set({"abc": 1, 'a': 2, "cc": "ss"})
print(info)
{'a', 'cc', 'abc'}
~~~
**add(key)**
通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:
~~~
>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.add(4)
>>> s
{1, 2, 3, 4}
~~~
**update( )方法**
此方法是用来迭代的往集合里添加元素
~~~
set1 = {1,2,3,4,5}
set1.update('6') #不能直接添加数字类型,因为数字类型不可迭代
print(set1) # {1, 2, 3, 4, 5, '6'}
set1.update('abc')
print(set1) #{1, 2, 3, 4, 5, 'c', 'a', '6', 'b'}
set1.update([1,7,8,9])
print(set1) #{1, 2, 3, 4, 5, 'b', 7, 8, 9, 'a', 'c', '6'}
~~~
## 删
**remove(key)**
通过remove(key)方法可以删除元素:
~~~
>>> s.remove(4)
>>> s
{1, 2, 3}
~~~
~~~
set1.remove('2') #指定删除一个元素,找不到就会报错
~~~
**pop**
~~~
set1 = {1,2,3,4,5}
set1.pop() #随机删除一个元素,将元素值返回
~~~
**clear**
~~~
set1.clear() #清空整个集合
~~~
**del**
~~~
del set1 #删除整个集合
~~~
**discard**
删除元素 如果元素不存在,不会做任何操作 也不会报错
~~~
s.discard('李四')
~~~
## 查
**for循环**
~~~
set1 = {1,2,3,4,5}
for s in set1:
print(s)
#结果如下:
# 1
# 2
# 3
# 4
# 5
~~~
## frozenset( )不可变集合
无法添加无法修改
~~~
set1 = {1,2,3,4,5}
set2 = frozenset(set1)
print(set2,type(set2))
#结果为:frozenset({1, 2, 3, 4, 5}) <class 'frozenset'>
#创建方法如下:
set3 = frozenset({1,2,3})
print(set3) # frozenset({1, 2, 3})
set4 = frozenset('abc') #迭代添加
print(set4) # frozenset({'a', 'b', 'c'})
~~~
## 集合的交并集操作
![](https://box.kancloud.cn/6d1f68023e7eb6caec54b17d2f5642de_967x547.png)
**交集、并集**
set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
* s1.union(s2) 并集
* s1.intersection(s2) 交集
~~~
set1 = {1,2,3,7,8}
set2 = {2,3,6,9}
print(set1&set2) #交集{2, 3}
print(set1|set2) #并集{1, 2, 3, 6, 7, 8, 9}
print(set1^set2) #反交集{1, 6, 7, 8, 9},就是交集之外的
print(set1-set2) #差集{8, 1, 7} 独有的
print(set2-set1) #差集{9, 6} 独有的
set1 = {1,2,3} #set1为set2的子集
set2 = {1,2,3,4,5} #set2为set1的超集
print(set1 < set2) #判断一个集合是否为另一个集合的子集,用' < '判断 如果是,返回:True
~~~
set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,
所以,同样**不可以放入可变对象**,
因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。
试试把list放入set,看看是否会报错
**子集和超集**
* s1.issubset(s2) s1是否是s2的子集
* s2.issuperset(s1) s2是否是s1的超集
**差集**
* s1.difference(s2)
**异或**
* s1.symmetric_difference(s2)
* `s1.symmetric_difference_update(s2)` 更新s1为异或的结果
# copy( )与 deepcopy()
这两种方法用于复制一个变量然后赋值给另一个变量。
copy( )----浅复制
简单来讲,用此方法复制后的变量与原变量对应的内存地址是不一样的,修改它第一层的元素,另一个变量不会被修改
但是如果他们有嵌套(如列表里嵌套列表),那么第二层嵌套的列表与另一个变量所对应的列表的地址就是一个内存地址了,
这个时候,如果修改第二层的元素,则另一个变量也会被修改
用法:
~~~
a = ['a','b','c']
b = a.copy()
print(b)
#结果为:['a', 'b', 'c']
~~~
他们的内存地是不同的,更改一个列表的第一层元素的值,另一个不会被更改,如下:
~~~
li1 = [1,2,[3,4],5]
li2 = li1.copy()
print(li1 is li2) #False
li2[0] = 0 #更改li2第一层的值,li1不会被修改
print(li1) #[1, 2, [3, 4], 5]
~~~
但是,如果我们要修改一个列表的第二层元素的话,另一个列表就会被修改了,如下:
~~~
li1 = [1,2,[3,4],5]
li2 = li1.copy()
print(li1 is li2) #False
li2[2][0] = 0 #更改li2第二层的值,li1就会被修改
print(li1) #[1, 2, [0, 4], 5]
~~~
**deepcopy( )----深复制**
~~~
import copy
li1 = [1,2,[3,4],5]
li2 = copy.deepcopy(li1)
print(li1 is li2) #False
li2[2][0] = 0 #更改li2第二层的值,li1也不会被修改
print(li1) #[1, 2, [3, 4], 5]
~~~
- python入门
- 软件安装
- anaconda使用
- py解释器
- 数据类型和变量
- 编码
- 字符串
- 格式化
- 数据类型
- 运算符
- list和tuple
- 列表生成式
- dict和set
- 切片和迭代
- set,list,tuple之间互换
- is和==
- 公共方法
- 反射操作
- 数学运算
- 类型转换
- 对象操作
- 序列操作
- 运算符
- 内置函数
- 交互操作
- 编译执行
- 引用
- 判断,循环
- 生成器
- 迭代器
- 函数
- 数据类型转换
- 空函数
- 参数
- 全局变量
- 返回值
- 递归
- 匿名函数
- 文件操作
- 打开和关闭
- 读写
- 备份文件
- 文件定位读写
- 重命名,删除
- 文件夹相关操作
- with
- StringIO和BytesIO
- 操作文件和目录
- 序列化
- 文件属性
- 面向对象
- 类和对象
- init()方法
- 魔法方法
- 继承
- 重写
- 多态
- 类属性,实例属性
- 静态方法和类方法
- 工厂模式
- 单例模式
- 异常
- 私有化
- 获取对象信息
- *args和**kwargs
- property属性
- 元类
- slots
- 定制类
- 枚举
- 模块
- 模块介绍
- 模块中的__name__
- 模块中的__all__
- 包
- 模块发布
- 模块的安装和使用
- 多模块开发
- 标准库
- 给程序传参数
- 时间
- 正则表达式
- GIL
- 深拷贝和浅拷贝
- 单元测试
- pyqt
- 安装
- 设置窗口图标和移动窗口
- 设置气泡提示和文本
- 图片展示
- 文本框控件
- 按钮控件
- 信号和槽
- 布局
- 对话框控件
- pygame
- 窗体关闭事件
- 显示图片
- 移动图片
- 文本显示
- 背景音和音效
- FPS计算
- surface
- 鼠标事件
- 函数式编程
- map/reduce
- filter
- sorted
- 返回函数
- 装饰器
- 偏函数
- 网络编程
- tcp
- udp
- socket
- epoll
- WSGI
- 多任务
- 多线程
- 多进程
- 分布式进程
- 协程
- 迭代器
- 生成器
- yield多任务
- greenlet
- gevent
- ThreadLocal
- asyncio
- async/await
- aiohttp
- 常用内建模块
- datetime
- collections
- base64
- struct
- hashlib
- hmac
- itertools
- urllib
- xml
- HTMLParser
- 常用第三方模块
- pillow
- requests
- chardet
- psutil
- 图形界面
- 海龟绘图
- Django
- 虚拟环境搭建
- ORM
- 模型类设计和表生成
- 模型类操作
- 关系查询
- 后台管理
- 配置mysql
- 字段属性和选项
- 查询
- 模型关联
- 路由
- 模板
- selenium
- 基本原理
- api
- 八种定位方式
- 元素的操作
- 多标签
- 多表单
- 鼠标,键盘
- 警告框
- 下拉框
- 执行js
- 等待
- cookie
- 封装
- unittest模块
- 断言
- 测试用例
- jmeter
- jmeter简介
- jmeter提取json
- 添加header和cookie
- 读取csv/txt文件
- 配置文件
- ant