python dict根据value找对应的key_一个不得不了解的Python库——collections

基本介绍

Python拥有一些内置的数据类型,比如str, int, list, tuple, dict等, collections模块在这些内置数据类型的基础上,提供了几个额外的数据类型,如下。这些类在平时Python代码中用处非常大,熟练掌握这个模块,可以大大简化Python代码,提高Python代码逼格。

import collections

print collections.__all__

['Counter', 'deque', 'defaultdict', 'namedtuple', 'OrderedDict', 'Hashable','Iterable', 'Iterator', 'Sized', 'Container','Callable', 'Set', 'MutableSet','Mapping', 'MutableMapping', 'MappingView', 'KeysView', 'ItemsView', 'ValuesView', 'Sequence', 'MutableSequence']

本文主要介绍collections库中常用的几个类:

  • Counter: 计数器,主要用来计数
  • deque: 双端队列,可以快速的从另外一侧追加和推出对象
  • OrderedDict: 有序字典
  • namedtuple: 生成可以使用名字来访问元素内容的tuple子类
  • defaultdict: 带有默认值的字典

Counter类

Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。

Counter类的创建

from collections import Counter

c1 = Counter() # 创建一个空的Counter类

c2 = Counter('zhongguo') # 从一个可iterable对象(list、tuple、dict、字符串等)创建

c3 = Counter({'a': 5, 'b': 1}) # 从一个字典对象创建

c4= Counter(a=3, b=8) # 从一组键值对创

most_common()方法

s = 'Nothing is difficult if you put your heart into it'

c = Counter(s)

print c.most_common(5)

[(' ', 9), ('i', 7), ('t', 6), ('o', 4), ('u', 4)]

键值的访问与计数器的更新

c = Counter("zhongguo")

print c['z'],c['o'],c['l']

output:1,2,0

#注意:不同于字典键值查找,当查找的键值不存在是计数器返回为0

#第一种更新方式--updatez增加

c.update('ren') # 使用另一个iterable对象更新

print c['n'] #2

d = Counter('niubi')

c.update(d) # 使用另一个Counter对象更新

print c['n'] #4

#第2种更新方式--subtract减少

c = Counter("zhongguo")

c.subtract('ren')

print c['n'] #0

d = Counter('niubi')

c.update(d)

print c['n'] #-1(是可以为负数的)

elements()方法以及删除键值

c = Counter(a=2, b=1, c=0, d=-1)

list(c.elements())

#['a', 'a', 'b'] #小于或等于0的不显示了

#删除键值

del c['a']

print c

#Counter({'b': 1, 'c': 0, 'd': -1})

一些基本操作

c1 = Counter(a=1, b=2)

c2 = Counter(a=2, b=3)

print c1+c2

print c1-c2 #不返回0或者负数计数

#Counter({'b': 5, 'a': 3})

#Counter()

sum(c.values()) # 所有计数的总数

c.clear() # 重置Counter对象,注意不是删除

list(c) # 将c中的键转为列表

set(c) # 将c中的键转为set

dict(c) # 将c中的键值对转为字典

c += Counter() # 移除0和负值

defaultdict 类

defaultdict 是 dict 的子类,因此 defaultdict 也可被当成 dict 来使用,dict 支持的功能,defaultdict 基本都支持。但它与 dict 最大的区别在于,如果程序试图根据不存在的 key 采访问 dict 中对应的 value,则会引发 KeyError 异常;而 defaultdict 则可以提供一个 default_factory 属性,该属性所指定的函数负责为不存在的 key 来生成 value。

from collections import defaultdict

my_dict = {}

# 使用int作为defaultdict的default_factory

# 将key不存在时,将会返回int()函数的返回值

my_defaultdict = defaultdict(int)

print my_defaultdict['a'] # 0

print my_dict['a'] # KeyError

#与Counter性质类似

#上面分别创建了空的 dict 对象和 defaultdict 对象,当程序试图访问 defaultdict 中不存在的 key 对应的 value 时,程序输出 defaultdict 的 default_factory 属性(int 函数)的返回值 0;如果程序试图访问 dict 中不存在的 key 对应的 value,就会引发 KeyError异常。

对比dict操作

###dict####

s = [('Python', 1), ('Swift', 2), ('Python', 3), ('Swift', 4), ('Python', 9)]

d = {}

for k, v in s:

# setdefault()方法用于获取指定key对应的value.

# 如果该key不存在,则先将该key对应的value设置为默认值:[]

d.setdefault(k, []).append(v)

print list(d.items())

#需要处理 key 不存在的情况,如果该key不存在,setdefault()方法就会先为该key设置一个默认的value。

###defaultdict###

s = [('Python', 1), ('Swift', 2), ('Python', 3), ('Swift', 4), ('Python', 9)]

# 创建defaultdict,设置由list()函数来生成默认值

d = defaultdict(list)

for k, v in s:

# 直接访问defaultdict中指定key对应的value即可。

# 如果该key不存在,defaultdict会自动为该key生成默认值

d[k].append(v)

print(list(d.items()))

相比于普通dict是不是方便很多。

deque类

deque是一个双向链表,针对list连续的数据结构插入和删除进行优化。它提供了两端都可以操作的序列,这表示在序列的前后你都可以执行添加或删除操作。

from collections import deque

d=deque()

类似于list方法

d.append(3)

d.append(8)

print d

#deque([3,8])

print len(d) #2,

d[0] #3

d[-1] #8

d.pop() #5,默认pop()抛出的是队列的最后一个元素

d.leftpop() #3

长度限制

d=deque(maxlen=10)

for i in range(20):

d.append(i)

#deque(10, 11, 12, 13, 14, 15, 16', 17, 18, 19, 20], maxlen=10)

#当限制长度的deque增加超过限制数时,左边会自动删除,这也符合队列的性质。

extend()方法

d=deque([1,2,3,4,5])

d.extend([6])

#deque([1,2,3,4,5,6])

d.extendleft([-2,-1,0])

#deque([-2,-1,0, 1, 2, 3, 4, 5, 6])

rotate()方法

b=deque("ABCDEFG")

print b

b.rotate(2)

print b

b.rotate(3)

print b

#deque(['A', 'B', 'C', 'D', 'E', 'F', 'G'])

#deque(['F', 'G', 'A', 'B', 'C', 'D', 'E'])

#deque(['C', 'D', 'E', 'F', 'G', 'A', 'B'])

OrderedDict类

OrderedDict 也是 dict 的子类,其最大特征是,它可以“维护”添加 key-value 对的顺序。简单来说,就是先添加的 key-value 对排在前面,后添加的 key-value 对排在后面。相比于dict更加灵活。

基础性质

from collections import OrderedDict

# 创建OrderedDict对象

dx = OrderedDict(b=5, c=2, a=7)

print dx # OrderedDict([('b', 5), ('c', 2), ('a', 7)])

d = OrderedDict()

# 向OrderedDict中添加key-value对

d['Python'] = 89

d['Swift'] = 92

d['Kotlin'] = 97

d['Go'] = 87

# 遍历OrderedDict的key-value对

for k,v in d.items():

print k, v

顺序

# 创建普通的dict对象

my_data = {'Python': 20, 'Swift':32, 'Kotlin': 43, 'Go': 25}

# 创建基于key排序的OrderedDict

d1 = OrderedDict(sorted(my_data.items(), key=lambda t: t[0]))

# 创建基于value排序的OrderedDict

d2 = OrderedDict(sorted(my_data.items(), key=lambda t: t[1]))

print(d1) # OrderedDict([('Go', 25), ('Kotlin', 43), ('Python', 20), ('Swift', 32)])

print(d2) # OrderedDict([('Python', 20), ('Go', 25), ('Swift', 32), ('Kotlin', 43)])

print(d1 == d2) # False

# OrderedDict能维护key-value对的添加顺序,因此即使两个 OrderedDict中的key-value对完全相同,但只要顺序不同,程序在判断它们是否相等时也依然会返回false

特殊方法

  1. popitem(last=True):默认弹出并返回最右边(最后加入)的 key-value 对;如果将 last 参数设为 False,则弹出并返回最左边(最先加入)的 key-value 对。
  2. move_to_end(key, last=True):默认将指定的 key-value 对移动到最右边(最后加入);如果将 last 改为 False,则将指定的 key-value 对移动到最左边(最先加入)

d = OrderedDict.fromkeys('abcde')

# 将b对应的key-value对移动到最右边(最后加入)

d.move_to_end('b')

print(d.keys()) # odict_keys(['a', 'c', 'd', 'e', 'b'])

# 将b对应的key-value对移动到最左边(最先加入)

d.move_to_end('b', last=False)

print(d.keys()) # odict_keys(['b', 'a', 'c', 'd', 'e'])

# 弹出并返回最右边(最后加入)的key-value对

print(d.popitem()[0]) # e

# 弹出并返回最左边(最先加入)的key-value对

print(d.popitem(last=False)[0]) # b

namedtuple类

namedtuple() 是一个工厂函数,使用该函数可以创建一个 tuple 类的子类,该子类可以为 tuple 的每个元素都指定宇段名,这样程序就可以根据字段名来访问 namedtuple 的各元素了,也可以根据索引来访问 namedtuple 的各元素。

基本属性

namedtuple(typename, field_names, *, verbose=False, rename=False, module=None)

  • typename:该参数指定所创建的 tuple 子类的类名,相当于用户定义了一个新类。
  • field_names:该参数是一个字符串序列,如 ['x','y']。此外,field_names 也可直接使用单个字符串代表所有字段名,多个字段名用空格、逗号隔开,如 'x y' 或 'x,y'。任何有效的 Python 标识符都可作为字段名(不能以下画线开头)。有效的标识符可由字母、数字、下画线组成,但不能以数字、下面线开头,也不能是关键字(如 return、global、pass、raise 等)。
  • rename:如果将该参数设为 True,那么无效的字段名将会被自动替换为位置名。例如指定 ['abc','def','ghi','abc'],它将会被替换为 ['abc', '_1','ghi','_3'],这是因为 def 字段名是关键字,而 abc 字段名重复了。
  • verbose:如果该参数被设为 True,那么当该子类被创建后,该类定义就被立即打印出来。
  • module:如果设置了该参数,那么该类将位于该模块下,因此该自定义类的 __module__ 属性将被设为该参数值。

from collections import namedtuple

# 定义命名元组类:Point

Point = namedtuple('Point', ['x', 'y'])

# 初始化Point对象,即可用位置参数,也可用命名参数

p = Point(11, y=22)

# 像普通元组一样用根据索引访问元素

print(p[0] + p[1]) # 33

# 执行元组解包,按元素的位置解包

a, b = p

print(a, b) # 11, 22

# 根据字段名访问各元素

print(p.x + p.y) # 33

print(p) # Point(x=11, y=22)

方法

  • _make(iterable):类方法。该方法用于根据序列或可迭代对象创建命名元组对象。
  • _asdict():将当前命名元组对象转换为 OrderedDict 字典。
  • _replace(**kwargs):替换命名元组中一个或多个字段的值。
  • _source:该属性返回定义该命名元组的源代码。
  • _fields:该属性返回该命名元组中所有字段名组成的元组。

my_data = ['East', 'North']

# 创建命名元组对象

p2 = Point._make(my_data)

print(p2) # Point(x='East', y='North')

# 将命名元组对象转换成OrderedDict

print(p2._asdict()) # OrderedDict([('x', 'East'), ('y', 'North')])

# 替换命名元组对象的字段值

p2._replace(y='South')

print(p2) # Point(x='East', y='North')

# 输出p2包含的所有字段

print(p2._fields) # ('x', 'y')

# 再次定义一个命名元组类

Color = namedtuple('Color', 'red green blue')

# 再次定义命名元组类,其字段由Point的字段加上Color的字段

Pixel = namedtuple('Pixel', Point._fields + Color._fields)

# 创建Pixel对象,分别为x、y、red、green、blue字段赋值

pix = Pixel(11, 22, 128, 255, 0)

print(pix) # Pixel(x=11, y=22, red=128, green=255, blue=0)

总结

看过上面的介绍是不是对collections模块有一定的理解了,是不是也已经知道了它的重要性,总之一句话,理解这个模块的各种方法实现,能够让你的代码有事半功倍的效果,而且相比传统的list,dict,用它可以让你的代码逼格更高,数不多说,快去学习了。

62f3c9935412dbea9ff439325c323edb.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值