深入dict与set

  • A+
所属分类:安全开发

DICT

dict,python中的字典,有key和value对应,属于mapping(关系映射)类型。通过isinstance(dict,Mapping)可以判断

from collections import Mapping
a = {'a':'a'}
print(isinstance(a,Mapping))

返回结果:

True

获取值

使用get和[]直接取值都可以,后者如果取值不存在就报错,前者不会,如果是修改键对应的值的话,使用第二种方法。

a = {'user':'langzi'}
print(a['user'])
print(a.get('user'))
# 获取值
a['user']='admin'
# 改变值

返回结果:

langzi
langzi

你还可以获取字典的所有键或者所有值,使用keys和values

啊 = {'user''langzi''age': 18}
print(啊)
print(啊.keys())
print(啊.values())
# 注意中文变量在python3中才可用

返回结果:

{'user''langzi''age': 18}
dict_keys(['user''age'])
dict_values(['langzi', 18])

还可以使用setdefault获取,setdefault() 方法和 get() 方法类似,返回指定键的值,如果键不在字典中,将会添加键并将值设置为一个指定值,默认为None。

a = {'user''langzi''age': 18}
print(a.setdefault('user','aaaaaaaaaaaa'))
print(a.setdefault('users','aaaaaaaaaaaa'))

返回结果:

langzi
aaaaaaaaaaaa

清空字典

直接将字典清空,包括内容与格式。

a = {'user':'langzi'}
a.clear()
print(a)
b = {'user':{'user':'admin'},'age':18}
b.clear()
print(b)

返回结果:

{}
{}

字典遍历修改值

字典在遍历的时候,如果要修改字典的键值对,则会报错:

比如:

a = {'80':'http','8080':'randhttp'}
for k,v in a.items():
    if v == 'http':
        del a[k]

报错内容:

RuntimeError: dictionary changed size during iteration

结局方法很多,随便列举一种

for k in list(a.keys()):
    if a[k] 
== 'http':
        del a[k]

删除字典中的某一对键值

使用del即可,举个例子:

a = {'user''langzi''age'18}
del a['user']
print(a)

返回结果:

{'age': 18}

复制字典

使用dict.copy()返回一个拷贝的对象,其实就是调用copy.copy()浅拷贝,修改拷贝后的对象会影响到原对象的值,因为浅拷贝只把值都是指向同一个对象。

生成字典

根据你的列表或者数组的内容,变成字典的键,值就是你自己随便折腾的,举两个例子。

a = ['user1','user2','user3']
b = dict.fromkeys(a,'None')
print(b)

返回结果:

{'user1''None''user2''None''user3''None'}

当然也可以这么写:

import random
a = {k:random.randint(1000,1020for k in range(10)}
print(a)

返回结果:

{0: 1009, 1: 1008, 2: 1001, 3: 1008, 4: 1019, 5: 1012, 6: 1010, 7: 1012, 8: 1019, 9: 1013}

字典合并

就像列表使用extend(本质上是调用append)合并,字典也有相似的用法,使用update。

a = {'user':'langzi'}
b = {'age':18}
a.update(b)
# 还可以这样传入a.update(home='china')
print(a)

返回结果:

{'user''langzi''age': 18}

判断是否有键

使用dice.has_key(key)即可,存在就返回True

获取键的总和

使用len(dict)即可。

循环字典

这个比较简单的,如果是for x in dict的话就是循环字典的键,如果for x,y in dict.iters()那么同时循环字典的键和值。

更多具体方法

传送门1

http://www.langzi.fun/Python%E5%AF%B9%E5%AD%97%E5%85%B8%E6%8E%92%E5%BA%8F.html

传送门2

http://www.langzi.fun/Python%E5%AD%97%E5%85%B8%E5%88%97%E8%A1%A8%E7%AD%9B%E9%80%89%E6%95%B0%E6%8D%AE.html

继承字典

其实list和dict都是可以被继承的,因为他们的数据结构本来就是一个类,当然可以被继承,但是不建议这么做。

SET

SET:集合,frozenset:不可变集合,集合是有无序和不重复的两个特点,所以常用来做去重,并且集合也是用{}包围起来的。

比如:

s = set('aaaaa')
print(s)

返回结果:

a

如果你直接使用a={},a.add(1)这样事会报错的,你比如先实例化一个集合,比如a=set(),然后再a.add(1)就可以。

添加数据

使用set.add('xxx'),但是如果是frozenset是无法添加修改数据的。

合并数据

使用set.update('xaxaxa')

删除数据

set.remove('xxx'):删除xxx,不存在xxx报错    
set.pop():删除并返回一个不确定元素
set.discard('xxx'):删除xxx,不存在xxx不报错

取交集与并集

交集:两个集合中都有的元素。并集:两个集合中所有的元素。

a = {'a','b','c'}
b = {'a','e','f'}
print(a|b)
# 取并集
print(a&b)
# 取交集

返回结果:

{'e''f''a''b''c'}
{'a'}

再举个例子:

a = {'a','b','c'}
b = {'a','e','f'}
print(a-b)
# 找出a中b没有的元素

返回结果:

{'b''c'}

SET与DICT都是使用hash存储,时间复杂度很低,相对来说性能很高。

dict与set的一些特性

  1. dict查找性能远大于list

  2. 在list中随着list数据增大,查找时间也会增大

  3. 在dict中随着dict元素增大,查找时间不会增大(因为dict存储原理是用哈希表)

  4. set的原理和dict一样,也是走哈希表方法(不可变对象)

  5. dict内存花销大,python中内部的对象都是dict进行包装的

  6. dict的顺序和元素添加顺序有关,添加数据有可能改变已有数据的顺序

概念:python中的dict并没有采用map中的红黑树结构做关联,而是使用效率更高的散列表,在最优情况下,散列表能够提供O(1)的搜索效率。


本文始发于微信公众号(安全研发):深入dict与set

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: