python高级(三)—— 字典和集合(泛映射类型)

2018-02-27 09:00:39来源:cnblogs.com作者:廖Sir人点击

分享

本文主要内容

可散列类型

泛映射类型

字典

    (1)字典推导式

  (2)处理不存在的键

集合

映射的再讨论

python高级——目录

文中代码均放在github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

可散列类型

'''    可散列数据类型(也称可hash)————我理解"可散列"就是"可hash"    可hash的对象需要实现__hash__方法,返回hash值;另外为了与其他对象比较还需要有__eq__方法    原子不可变数据类型(str、bytes和数值类型)都是可散列的,可散列对象必须满足下列要求:    (1)实现了__hash__方法,并且所得到的hash值是不变的    (2)实现了__eq__方法,用来比较    (3)若a == b 为真,那么hash(a) == hash(b)也是真'''# 创建类Foo,并实现__hash__和__eq__class Foo:    def __init__(self, name):        self.name = name    def __hash__(self):        print("正在hash...")        return hash(self.name)    def __eq__(self, other):        print("正在比较...")        return self.name == other.name    def __repr__(self):        return self.nameif __name__ == "__main__":    f1 = Foo("小李")    f2 = Foo("小红")    f3 = Foo("小李")    s = set([f1, f2, f3])        # 集合实现不重复的原理正好利用了散列表    print(s)                     # {小红, 小李}    print( f1 == f3, hash(f1) == hash(f3))      # True True 满足可散列对象的第三个条件
'''    对于元组来说,只有当一个元组包含的所有元素都是可hash的情况下,它才是可hash的'''t1 = (1, 2, 3, [1, 2])   # 元组里的列表的值是可变的,所以不可hashtry:    print(hash(t1))except Exception as e:    print(e)             # unhashable type: 'list't2 = (1, 2, 3, (1, 2))   # 元组里的元素都是不可变的,并且第二层元组里面的元素也不可变,所以可hashprint(hash(t2))          # 3896079550788208169t3 = (1, 2, 3, frozenset([1, 2]))print(hash(t3))          # -5691000848003037416

泛映射类型

'''    泛映射类型就是广义上的对应关系,在数学中,我们将集合A对应集合B中的对应法则称为"映射"(Mapping)    同样,在python里,我们称"键值对"为映射,这其实也是一种对应法则    如果一个数据类型是映射,那么它肯定属于collections.abc.Mapping,可使用isinstance函数测试    PS: 字典是 Python 语言中唯一的映射类型。映射类型对象里哈希值(键) 和指向的对象(值)是一对多的关系。'''from collections import abc# 我们测试一些常用的类型是不是映射if __name__ == "__main__":    print(isinstance({}, abc.Mapping))      # True   字典是典型的键值对    print(isinstance([1, 2], abc.Mapping))  # False  列表是序列    print(isinstance((1, 2), abc.Mapping))  # False  元组是序列    print(isinstance('adfasfd', abc.Mapping))  # False  字符串也是序列
'''   大家可以查看_collections_abc.py源代码,里面基本的类型包含:    ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator",    "Hashable", "Iterable", "Iterator", "Generator",    "Sized", "Container", "Callable",     "Set", "MutableSet",     "Mapping", "MutableMapping",     "MappingView", "KeysView", "ItemsView", "ValuesView",     "Sequence", "MutableSequence",    "ByteString",    ]'''
'''    如果我们自己想定义一个映射类型的对象,那么必须实现__getitem__、__iter__、__len__方法        PS:关于该部分的原理,本人暂未查看说明文档,毕竟现实中几乎不可能自定义映射;有兴趣的同志可深入钻研。'''class Foo(abc.Mapping):    def __init__(self, name):        self.name = name    def __getitem__(self, item):        return self.name    def __iter__(self):        return iter(str(self.name))    def __len__(self):        return len(self.name)print(isinstance(Foo("123"), abc.Mapping))      # True

字典

'''    字典是python内置类型中唯一的映射,先看创建字典的几种方法    1、对象创建    2、大括号    3、zip'''if __name__ == "__main__":    # 1、利用实例化对象的方法创建    a = dict(key1=1, key2=2, all=[1, 2, 3])    b = dict([('key3', 3), ('key4', 4)])    c = dict({"key5": 5, "key6": 6})    print("a:", a)     # a: {'key1': 1, 'all': [1, 2, 3], 'key2': 2}    print("b:", b)     # b: {'key3': 3, 'key4': 4}    print("c:", c)     # c: {'key6': 6, 'key5': 5}    # 2、直接使用大括号    d = {"key7": 7, "key8": 8}    print("d:", d)     # d: {'key8': 8, 'key7': 7}    # 3、使用zip    e = dict(zip(("key9", "key10", "key11"), [9, 10, 11]))    print("e:", e)     # e: {'key11': 11, 'key10': 10, 'key9': 9}
'''    字典推导式:字典推导式的创建方法同列表推导式类似    以下直接引用《流畅的python》中的例子'''if __name__ == "__main__":    DIAL_CODES = [        (86, 'China'),        (91, 'India'),        (1, 'United States'),        (62, 'Indonesia'),        (55, 'Brazil'),        (92, 'Pakistan'),        (880, 'Bangladesh'),        (234, 'Nigeria'),        (7, 'Russia'),        (81, 'Japan'),    ]    country_code = {country: code for code, country in DIAL_CODES}    print(country_code)   # {'Russia': 7, 'Indonesia': 62, 'Brazil': 55, 'China': 86, 'India': 91, 'Bangladesh': 880, 'Pakistan': 92, 'United States': 1, 'Nigeria': 234, 'Japan': 81}    code_upper = {code: country.upper() for country, code in country_code.items() if code < 66}    print(code_upper)     # {1: 'UNITED STATES', 7: 'RUSSIA', 62: 'INDONESIA', 55: 'BRAZIL'}
'''    处理找不到的键    在实际场景中,当使用d[key]的方法查找数据的时候,如果找不到该键,python会抛出KeyError异常;    如果是取值操作,可以使用d.get(key, default)来解决,可以给找不到的键一个默认的值    但是如果要给更新某个不存在键对应的值的时候,就稍显麻烦了,可以使用以下方法解决:        1、用setdefault处理dict找不到的键        2、使用defaultdict对象        3、__missing__方法'''class Foo:    def __init__(self, name=None):        self.name = name    def __repr__(self):        return str(self.name)    def setattr(self, key, value):        self.__setattr__(key, value)        return selfif __name__ == "__main__":    d1 = {}    print(d1.get("key", "default"))   # default   使用d.get(key, default)的方法取值    # 1、用setdefault处理dict找不到的键    d2 = {}    d2.setdefault("key", [x for x in "adfaf"])  # setdefault虽然是set名字,但是是取值操作,只有当键不存在时才进行赋值,并返回该值    l = d2.setdefault("key", [])    print(l)                                    # ['a', 'd', 'f', 'a', 'f']    d2.setdefault("key2", []).extend([1, 2, 3]) # 返回空列表,所以可在后面直接使用方法extend    print(d2)                                   # {'key': 'default', 'key2': [1, 2, 3]}    # 2、使用defaultdict对象    #  在python中,还有一些dict的变种类型,defaultdict为其中一种,位于collections中    from collections import defaultdict    dic = defaultdict(list)                    # 将list的构造方法作为default_factory(只有__getitem__找不到值时调用)    dic["key"].extend([1, 2, 3])               # dic中不含有"key"键,此时default_factory会被调用,创造一个空列表,并连接[1, 2, 3]    print(dic["key"])                # [1, 2, 3]    dic = defaultdict(Foo)           # 将Foo的构造方法作为default_factory创建一个defaultdict    print(dic["key"].setattr("name", "default"))                # default    # 3、__missing__方法    # 所有的映射类型在找不到键的时候,都会牵扯到__missing__方法;如果在__getitem__找不到键的时候,python就会自动调用它    # 另外,__missing__方法只会被getitem调用,对get或者__contains__没有影响    class My_dict(dict):        def __missing__(self, key):            print("正在调用__missing__...")    mdict = My_dict(one=1, two=2, three=3)    print(mdict)     # {'two': 2, 'three': 3, 'one': 1}    mdict["key"]     # 正在调用__missing__...

python高级系列文章目录

python高级——目录

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台