zoukankan      html  css  js  c++  java
  • Python字典和集合

    1、泛映射类型

    collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象类,他们的作用是为dict和其他类似的类型定义形式接口。

    标准库里所有映射类型都是利用dict来实现的,因此他们有个共同的限制,只有可散列的数据类型才能用作这些映射里的键。

    可散列的数据类型在这个对象的生命周期中,他的散列值是不变的,而且这个对象需要实现__hash__()方法,还要有__eq__()方法。

    ▲ 原子不可变数据类型(str、bytes和数值类型)、frozenset都是可散列类型。

    ▲ 只有当一个元组包含的所有元素都是可散列类型的情况下,它才是可散列的。

    字典提供了多种构造方法:

    >>> a = dict(name='Li', sex='girl')
    >>> b = {'name':'Li', 'sex':'girl'}
    >>> c = dict(zip(['name','sex'], ['Li','girl']))
    >>> d = dict([('name':'Li'), ('sex':'girl')])
    >>> e = dict({'name':'Li', 'sex':'girl'})
    >>> a == b == c == d == e
    True
    

    2、字典推导、默认值

    2.1、字典推导

    从任何以键值对作为元素的可迭代对象中构建出字典。

    >>> DIAL_CODE = [
    ...    (86,'China'),
    ...    (1,'United States'),
    ... ]
    
    >>> country_code = {country:code for code,country in DIAL_CODE}
    {'China': 86, 'United States': 1}
    
    >>> {country:code for country,code in country_code.items() if code > 50}
    {'China': 86}
    

    2.2、用setdefault处理找不到的键

    在不进行二次查找的情况下更新列表

    my_dict.setdefault(key, []).append(new_value)
    
    # 等于
    
    if key not in my_dict:
        my_dict[key] = []
    my_dict[key].append(new_value)
    

    3、映射的弹性键查询

    某个键在映射中不存在时,我们也希望通过这个键读取值的时候能得到一个默认值。

    可以使用defaultdict类型,或者自定义一个dict的子类,实现__missing__方法。

    、在实例化一个defaultdict的时候,需要给构造方法提供一个可调用对象,这个可调用对象会在__getitem__找不到键的时候被调用,让__getitem__返回某种默认值。

    如:dd = defaultdict(list) , dd['new_key']

    如果new_key在dd中不存在,表达式dd['new_key']会按如下步骤执行:

    (1)、调用list() 建立一个新列表。

    (2)、把这个新列表作为值,‘new_key’作为键,放到dd中。

    (3)、返回这个列表的引用。

    ▲、这个用来生成默认值 list 的可调用对象存放在名为 default_factory 的实例属性里。

    ▲、如果在创建defaultdict时没有指定 default_factory ,查询不存在键会触发 keyError

    ▲、defaultdict 里的 default_factory ,只会在__getitem__里被调用(dd[k]),而dd.get(k)则会返回None。

    特殊方法__missing__,只会被__getitem__调用。

    提供__missing__方法对get或者__contains__(in 运算符会用到这个方法)这些方法的使用没有影响。

    4、字典的变种

    collections.OrderedDict:添加键的时候后会保持顺序

    >>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
    >>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
    OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

    collections.ChainMap:容纳不同的映射对象,查找操作时,这些对象被当作一个整体被逐个查找。

    collections.Counter:整数计数器。 元素被存储为字典键,它们的计数被存储为字典值。

    collections.USerDict :让用户继承写子类。对一个字典对象的封装。其实例的内容保存在一个普通的字典当中,可以通过 UserDict 实例的属性 data 访问。

    5、不可变映射类型

    types模块引入了一个封装类名叫MappingProxyType。如果给这个类一个映射,它会返回一个只读的映射视图

    >>> from types import MappingProxyType
    >>> d = {'1':'one'}
    >>> d_proxy = MappingProxyType(d)
    >>> d_proxy
    mappingproxy({'1': 'one'})
    
    >>> d_proxy['1']
    'one'
    >>> d_proxy['2'] = 'two'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'mappingproxy' object does not support item assignment
    >>> d['2'] = 'two'
    >>> d_proxy
    mappingproxy({'2': 'two', '1': 'one'})

    6、集合论

    集合的本质是许多唯一对象的聚集。所以,集合可以用于去重。

    集合中的元素必须是可散列的,set类型本身是不可散列的,但是forzenset可以。所以可以创建一个包含不同frozenset的set。

    空集合:set()

    集合同样有属于他的集合推导

    >>> from unicodedata import name
    >>> {chr(i) for i in range(32,256) if 'SIGN' in name(chr(i),'')}
    {'xa2', 'xac', '§', '±', 'xa9', 'xb5', 'xae', '°', '$', 'xa3', '=', '+', '¤', '%', '÷', '<', 'xa5', 'xb6', '>', '#', '×'} 

    7、字典中的散列表

    散列表是一个稀疏数组(总是有空白元素的数组)。散列表里的单元叫做表元。

    在dict的散列表中,每一个键值对都占用一个表元,每个表元都有两个部分,一个是对键的引用,另一个是对值得引用。

    所有表元的大小一致,所以可以通过偏移量来读取某个表元。

    Python会设法保证大概还有三分之一的表元是空的,在快要达到阈值的时候,原有的散列表会被复制到一个更大的空间里面。

    如果要把一个对象放入散列表,那么首先要计算这个元素键的散列值。

    内置的hash()方法用于所有内置对象,自定义对象调用hash()实际上运行自定义的__hash__。

    如果两个对象在比较时是相等的,那他们的散列值必须相等。如(1 == 1.0)

    ▲ 散列值在索引空间中尽量分散开,越是相似的但不相等的对象,散列值的差别应该越大。如(1.0001和1.0002)

    散列表算法:为了获取my_dict[search_key]的值

    (1)首先调用hash(search_key)计算search_key的散列值,把这个值最低几位数字当做偏移量,在散列表里查找表元。

    (2)若找到的表元是空的,抛出KeyError异常

    (3)若不为空,表元里会有一对found_key:found_value。进行检验search_key == found_key是否为真

    (4)相等则返回found_value。不相等则称为散列冲突。

    为了解决散列冲突,算法会在散列值中另外再取几位经过计算处理,把新得到的数字再当做索引来寻找表元。

    一个可散列对象必须满足以下条件

    (1)支持hash()函数,并且通过__hash__()方法得到的散列值是不变的。

    (2)通过__eq__()方法检测相等性。

    (3)若a == b为真,则hash(a) == hash(b)也为真。

    所有由用户自定义的对象默认都是可散列的。因为他们的散列值由id()来获取,而且他们都不相等。

    ▲ 字典在内存中开销巨大,典型的空间换时间。

    ▲ 键的次序取决于添加顺序

    ▲ 往字典添加新键可能会改变已有键的顺序(字典扩容决定)

    set的实现也依赖散列表,散列表里存放的只有元素的引用

    1. 集合里的元素必须是可散列的。
    2. 集合很消耗内存。
    3. 可以很高效地判断元素是否存在于某个集合
    4. 元素的次序取决于被添加到集合里的次序
    5. 往集合里添加元素,可能会改变集合里已有元素的次序。
  • 相关阅读:
    20179311《网络攻防实践》第八周作业
    20179311《网络攻防实践》第七周作业
    20179311《网络攻防实践》第六周作业
    20179311《网络攻防实践》第五周作业
    20179311《网络攻防实践》第四周作业
    20179311《网络攻防实践》第三周作业
    20179311《网络攻防实践》第二周作业
    python的 Function Annotations学习笔记
    测试如何快速了解一个产品、需求、任务(海盗派测试分析)
    基于Jmeter和Jenkins搭建性能测试框架
  • 原文地址:https://www.cnblogs.com/5poi/p/11143108.html
Copyright © 2011-2022 走看看