字典
ps:数据类型分类:1、不可变数据类型:元组、bool、int、str、(也被称为可哈希)
2、可变数据类型:list、dict(不可哈希)
字典的Key必须为不可变数据类型,但字典的值value可以为任意数据类型
dict 的优点:可以使用二分查找查询、可以存储大量的关系型数据
特点:在python3.5之前的版本,字典是无序的
字典的增
dic = {'name':'haohao'} dic['age'] = 22 # 若无键值对,则增加键值对 print(dic) dic['name'] = 'huahua' # 若有键值对,则值覆盖 print(dic)
dic = {'name': 'HaoHao'} dic.setdefault('age', 22) # 若无键值对,则增加键值对 print(dic) dic.setdefault('name', 'HuaHua') # 若有键值对,则不执行操作 print(dic)
字典的删
dic = {'name': 'HaoHao', 'age': 22, 'hobby': 'IT'} s = dic.pop('name', None) # 若键值存在,则删除键,返回值;若不存在返回None(可自定义) print(s)
dic = {'name': 'HaoHao', 'age': 22, 'hobby': 'IT'} k,v = dic.popitem() # 随机删除键值对,返回删掉的键值对 print(k,v)
dic = {'name': 'HaoHao', 'age': 22, 'hobby': 'IT'} dic.clear() # 清空字典 print(dic)
dic = {'name': 'HaoHao', 'age': 22, 'hobby': 'IT'} del dic['name'] # 删除键'name',没有则会报错 print(dic) del dic # 删除字典 print(dic)
字典的改
dic = {'name': 'HaoHao', 'age': 22, 'hobby': 'IT'} dic['name'] = 'HuaHua' # 直接对键值进行修改 print(dic)
dic = {'name': 'HaoHao', 'age': 22, 'hobby': 'IT'} dic2 = {'name': 'HuaHua'} dic2.update(dic) # dic的键值对对dic2进行覆盖添加 print(dic2)
字典的查
dic = {'name': 'HaoHao', 'age': 22, 'hobby': 'IT'} l1 = dic.keys() # 字典的Key放入列表 l2 = dic.values() # 字典的值放入列表 l3 = dic.items() # 将字典的键值对构成一个小元组,放入列表 print(l1, '\n', l2, '\n', l3) for k, v in l3: # 通过循环查询输出键值对 print(k,v) s = dic.get('name1', None) # 通过get获取键值信息,查到后返回对应值,若没有查到返回None(可自定义) print(s)
字典的嵌套
dic = {'sushe':{1:{'name': 'HaoHao', 'age': 22, 'hobby': 'IT'}, 2:{'name': 'HuaHua', 'age': 20, 'hobby': 'IT'}, 3:{'name': 'AnShao', 'age': 22, 'hobby': 'IT'}}, 'school': 'ShiFan'} dic['sushe'][4] = {'name': 'QianGe', 'age': 23, 'hobby': 'IT'} # 添加新的建值对 dic['sushe'][2]['name'] = dic['sushe'][2]['name'].upper() # 将字典中的某个字符串大写 print(dic)
小知识点总结
1、python2与python3的区别
python2中 print 'abc' 可以加()也可以不加
range() xrange()
raw_input()
python3中 print ('abc')必须加()
range()
input()
2、= == is id
= 赋值
== 比较值是否相等
is 比较内存地址
id 内容地址
l1 = [1, 2, 3] l2 = [1, 2, 3] print(l1 is l2) l3 = l1 print(l1 is l3) print(id(l1), id(l2), id(l3))
3、int str
注意:数字和字符串类型有小数据池(可以节省内存空间)
数字的范围 -5~256
字符串:1、不能有特殊字符;2、s*20还是同一个地址,但s*21以后就是不同地址了(python3.7第二点好像不适用)
i1 = 6 i2 = 6 print(i1 is i2, id(i1), id(i2)) s1 = 'abc' s2 = 'abc' print(s1 is s2, id(s1), id(s2))
4、(1)多个编码规则之间的二进制是不能相互识别的,互相之间会产生乱码
(2)文件的存储、传输的时候不能是unicode编码方式(可以是utf-8、utf-16、gbk、gb2312等)
(3)python3的str 在内存中是用unicode编码的,在存储和传输时要转换成bytes类型(utf-8、gbk、gb2312)
ps:编码类型的转换方式
对于英文: str :表现形式:s = 'alexi' 编码方式为:01010101······(unicode),
bytes: 表现形式:s = b'alexi' 编码方式为:010101010·······(utf-8、gbk、gb2312)
对于中文: str : 表现形式: s = '中国' 编码方式为: 0101011110······(unicode)
bytes: 表现形式:s = b'\xe4\xb8\xad\xe5\x9b\xbd' 编码方式为:01010100·····(utf-8、gbk、gb2312)
如何将str 转换为 bytes编码方式?encode()
s1 = '中国' s2 = s1.encode('utf-8') print(s2)
5、for 、 enumerate 、range
for:用户按照循环顺序可以遍历可迭代对象的内容
msg = 'akjshgfksg' for i in msg: print(i) li = [1, 2, 5, 6, 'we'] for i in li: print(i) dic = {'name': 'haohao', 'age': 22} for k,v in dic.items(): print(k, v)
enumerate: 枚举,对于可迭代对象进行遍历时,可同时获得索引和元素,可自定义索引开始值
li = ['haohao', 'huahua', 'xinghui', 'anshao', 'qiange'] for i in enumerate(li): print(i, type(i)) for index, name in enumerate(li,1): print(index, name) for index, name in enumerate(li, 100): # 起始位置默认是0,可更改 print(index, name)
range: 指定范围,生成指定数字列表
for i in range(10): print(i) for i in range(0, 10, 2): # 可以设置步长 print(i) for i in range(10, 0, -1): # 倒序时要设置负步长 print(i)
基础数据类型补充
list: 在循环列表时要注意不要删除列表中的内容,因为列表时可变数据类型,在删除列表中内容后会影响循环
dict:补充一种字典的建立方式
dic = dict.fromkeys([1, 2, 3], []) # 迭代添加Key,添加同样的值 print(dic) dic[1].extend('泰格') dic[2].append('二哥') print(dic) # 要注意的是,这样建的字典和直接定义的字典的不同之处,这种字典中修改一个键值,所有的都会改变,要注意与下面方式的区别
dic = {1: [], 2: [], 3: []} print(dic) dic[1].extend('泰格') dic[2].append('二哥') print(dic)
同样,字典也属于可变数据类型,因此与列表一样,在循环字典时不能删除字典的键值对,当想删除字典的键值对时,应
先将想要删除的键写入一个列表中,然后在通过循环列表删除字典中的键值对。
dic = {1: [], 2: [], 3: [], 4: []} li = [] for i in dic: if i%2 == 0: # 删除字典中的偶数键值对 li.append(i) for i in li: del dic[i] print(dic)
ps:小知识 0 '' [] {} set() 转化为 bool 时为False
元组:当元组中只有一个元素时,不加逗号就不是元组
tu1 = (1) tu2 = (1,) print(type(tu1), type(tu2))
集合
集合是可变数据类型,但集合里面的元素必须是不可变的元素,集合是无序的、不重复的
集合的增
set = {1, '2', '3', 4, 'q'} set.add('a') print(set) set.update('aq23') # 迭代增加,但不会重复 print(set)
集合的删
set = {'w', 't', 'a', 'n', 'p'} s = set.pop() # 随机删除,有返回值 print(s, set)
set = {'w', 't', 'a', 'n', 'p'} set.remove('n') # 按元素删 print(set)
set1 = {'w', 't', 'a', 'n', 'p'} set1.clear() # 清空集合 print(set1) del set1 print(set1) # 删除集合
交集:输出集合1和集合2中重复的元素
set1 = {1, 2, 3, 4, 5} set2 = {4, 5, 6, 7, 8} print(set1 & set2) print(set1.intersection(set2))
并集:输出集合1和集合2中的元素,注意重复的元素只输出一次
set1 = {1, 2, 3, 4, 5} set2 = {4, 5, 6, 7, 8} print(set1 | set2) print(set1.union(set2))
反交集:输出集合1和集合2中不共有的元素
set1 = {1, 2, 3, 4, 5} set2 = {4, 5, 6, 7, 8} print(set1 ^ set2) print(set1.symmetric_difference(set2))
差集:输出集合1中集合2没有的元素
set1 = {1, 2, 3, 4, 5} set2 = {4, 5, 6, 7, 8} print(set1 - set2) print(set1.difference(set2))
子集与超集:如果集合1中所有的元素集合2中都有,相反却不成立,则集合1为2的子集,2为1的超集
set1 = {1, 2, 3, 4, 5} set2 = {1, 2, 3, 4, 5, 6, 7, 8} print(set1 < set2) print(set1.issubset(set2)) print(set2 > set1) print(set2.issuperset(set1))
ps:小技巧补充:因为集合中没有重复元素,所以可以利用集合的特性进行去重
li = [1, 2, 3, 4, 22, 33, 1, 2, 3, 5, 6, 4] set1 = set(li) li = list(set1) print(li)
集合的深浅copy
1、赋值运算
l1 = [1, 2, 3, {'name': 'HaoHao','age': 22}, 4] l2 = l1 l1[0] = 111 l1[3]['name'] = 'HuaHua' print(l1,l2)
出现这种结果是因为l2和l1指向了同一个内存地址,所以最后的结果相同
2、浅拷贝copy
l1 = [1, 2, 3, {'name': 'HaoHao','age': 22}, 4] l2 = l1.copy() print(l1,id(l1)) print(l2,id(l2)) l1[1] = 222 print(l1,id(l1)) print(l2,id(l2)) l1[3]['name'] = 'HuaHua' print(l1[3], id(l1[3])) print(l2[3], id(l2[3]))
出现这种结果的原因是对于浅copy来说,第一层创建了新内存地址,而对第二层甚至更深层来说指向的仍是同一个地址,
所以对这些层来说还依然保持着一致性。
3、深层拷贝deepcopy
import copy l1 = [1, 2, 3, {'name': 'HaoHao','age': 22}, 4] l2 = copy.deepcopy(l1) print(l1,id(l1)) print(l2,id(l2)) l1[1] = 222 print(l1,id(l1)) print(l2,id(l2)) l1[3]['name'] = 'HuaHua' print(l1[3], id(l1[3])) print(l2[3], id(l2[3]))
对于深层拷贝来说,两个文件保持完全独立,不会有任何关联,无论多少层,改变任何一个元素另外一个都不会改变