前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2017年9月4日

2017年9月4日

作者头像
阿章-python小学生
发布2018-05-18 17:00:14
8610
发布2018-05-18 17:00:14
举报
  1. 映射类型的抽象基类是collections.abc模块中的Mapping和MutableMapping。 他们只是为dict和其他类型定义形式接口。但是不会像java一样,所有的类都继承它或者实现它。 实际使用的时候只需要继承dict或是collections.UserDict(更常用),它只起到了isinstance判定类型的时候的作用。
from collections.abc import Mapping, MutableMapping

my_dict = {}
print(isinstance(my_dict, Mapping))
print(isinstance(my_dict, MutableMapping))
[Out]
True
True
  1. 用setdefault可以优雅的处理找不到的键。比如统计单词出现频率
index= {}
occurences = index.get(word,[])
occurences.append(location)
index[word] = occurrences

这三行代码可以简写为一行

index = {}
index.setdefault(word,[]).append(location)

虽然两者结果是一样的,但是三行代码的那种至少要经过两次键查询,而一行代码的只需要一次键查询。

  1. 处理上面的问题还有一种办法,使用collections.defaultdict,在实例化defaultdict的时候需要给构造 方法传递一个callable对象,这种callable对象会在gititem找不到键的时候调用。
index = collections.defaultdict(list)
index[word].append(location)

defaultdict里的default_factory属性通过defaultdict的构造方法赋值,并且只有在getitem中被调用,在其他地方如get(k)时不发生作用,没有还是返回默认None。

  1. 上面方法还可以通过集成dict,覆盖里面的missing方法来实现,missing方法在getitem找不到键的时候被调用。但是常用的不是继承dict而是继承collections.UserDict, UserDict是用100%python实现了一遍dict,而dict使用了很多捷径导致我们必须重写很多方法。而且UserDict不是dict的子类,但是有一个属性data是dict的实例,data属性是UserDict数据最终存储的地方。 这样可以避免子类在实现setitem的时候产生不必要的递归,也可以让contains代码更简洁。
import collections


class strKeyDict(collections.UserDict):
    def __missing__(self, key):
        if isinstance(key, str):
            raise KeyError
        # 如果不加判断当键不存在的时候会无限递归
        return self[str(key)]

    def __contains__(self, key):
        return str(key) in self.data

    def __setitem__(self, key, value):
        self.data[str(key)] = value
字典的变种
  1. collections.OrderedDict可以保证顺序的dict,有popitem方法,默认删除的是 最后一个元素可以通过关键字参数popitem(last=False)来删除第一个被添加进去的元素
  2. collections.ChainMap可以通过构造函数传入多个不同的映射对象。从第一个开始查找找不到再找第二个。。 可以用作嵌套作用域的语言做解释器的时候用,可以用一个映射对象来代表一个作用域的上下文。
import builtins
from collections import ChainMap

pylookup = ChainMap(locals(), globals(), vars(builtins))
  1. collections.Counter会给键加一个计数器,每次更新键的时候都会增加这个计数器。可用作散列表对象计数或多重集合。most_comman(n) 返回最常见的n个键和他们的计数。
import collections

ct1 = collections.Counter('fafdsfdfadfsdf')
print(ct1)
ct1.update('aaaaaa')
print(ct1)
print(ct1.most_common(2))
ct2 = collections.Counter(a=3, b=4)
print(ct2)
ct = ct1 + ct2
print(ct)
[Out]
Counter({'f': 6, 'd': 4, 'a': 2, 's': 2})
Counter({'a': 8, 'f': 6, 'd': 4, 's': 2})
[('a', 8), ('f', 6)]
Counter({'b': 4, 'a': 3})
Counter({'a': 11, 'f': 6, 'd': 4, 'b': 4, 's': 2})
  1. 不可变映射类型虽然没有,但是types模块有一个MappingProxyType返回映射的一个只读视图, 但是他是动态的,所以原映射改了他也能看到,但是无法通过它直接修改。
from types import MappingProxyType

d = {1: 'A'}
d_proxy = MappingProxyType(d)
print(d_proxy)
# [Out] {1: 'A'}
print(d_proxy[1])
# [Out] A
# d_proxy[2] = 'x'
# TypeError: 'mappingproxy' object does not support item assignment
d[2] = 'B'
print(d_proxy)
# [Out] {1: 'A', 2: 'B'}
print(d_proxy[2])
# B
  1. 集合可以用&求交集,用|求并集,用-求差集,用^求对称差集。应该多用字面量.
from dis import dis

dis('{1}')

dis('set([1])')

输出

也就是说用字面量直接调用BUILDSET字节码,代替了3个操作:LOADNAME,BUILDLIST,CALLFUNCTION. set的抽象形式接口定义在collections.abc.Set和collections.abc.MultipleSet中。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-09-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python全栈布道师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 字典的变种
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档