python3-cookbook读书笔记(二)

1.6 字典中的key映射多个值

映射的多个值需要放到另外的容器,如list、set等。

主要是collections模块的defaultdict函数和dict自带的setdefault函数

from collections import defaultdict

d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)
d = {} # 一个普通的字典
d.setdefault('a', []).append(1)
d.setdefault('a', []).append(2)
d.setdefault('b', []).append(4)

两者的区别:defaultdict函数会在访问的key不存在时也会创建映射实体如list等

setdefault函数每次调用都得创建新的key的实例

1.7 字典排序

创建一个字典,在迭代和序列化的时候控制元素的排序

主要是用collections的OrderDict

from collections import OrderedDict

d = OrderedDict()
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['grok'] = 4
# Outputs "foo 1", "bar 2", "spam 3", "grok 4"
for key in d:
    print(key, d[key])

主要用于序列化或编码成其他格式时有严格的顺序要求,如json编码

>>> import json
>>> json.dumps(d)
'{"foo": 1, "bar": 2, "spam": 3, "grok": 4}'
>>>

注意:OrderedDict类的大小是普通字典的两倍,因为其内部还维护了一个双向链表

1.8 字典的运算

对字典的最大值、最小值、排序等运算

主要是zip()min() max() sorted()函数的结合使用

其中zip() 函数将字典key和value反转,达到按照value的排序目的

这样做的原因min() max() sorted()这些计算函数只能作用于字典的key

min() max() sorted()就将zip处理后创建的迭代器就行运算

prices = {
    'ACME': 45.23,
    'AAPL': 612.78,
    'IBM': 205.55,
    'HPQ': 37.20,
    'FB': 10.75
}
min_price = min(zip(prices.values(), prices.keys()))
# min_price is (10.75, 'FB')
max_price = max(zip(prices.values(), prices.keys()))
# max_price is (612.78, 'AAPL')
prices_sorted = sorted(zip(prices.values(), prices.keys()))
# prices_sorted is [(10.75, 'FB'), (37.2, 'HPQ'),
#                   (45.23, 'ACME'), (205.55, 'IBM'),
#                   (612.78, 'AAPL')]

注意: zip() 函数创建的是一个只能访问一次的迭代器;在执行 min()max() 操作的时候,如果恰巧最小或最大值有重复的,那么拥有最小或最大键的实体会返回

1.9 查找字典的相同点

主要使用字典的keys()函数items()函数的返回结果进行集合运算

a = {
    'x' : 1,
    'y' : 2,
    'z' : 3
}

b = {
    'w' : 10,
    'x' : 11,
    'y' : 2
}
# Find keys in common
a.keys() & b.keys() # { 'x', 'y' }
# Find keys in a that are not in b
a.keys() - b.keys() # { 'z' }
# Find (key,value) pairs in common
a.items() & b.items() # { ('y', 2) }

字典的 keys() 方法返回一个展现键集合的键视图对象,

字典的 items() 方法返回一个包含 (键,值) 对的元素视图对象

以上的两个对象都支持集合运算

字典的 values() 方法也是类似,但是它并不支持这里介绍的集合操作。是因为值视图不能保证所有的值互不相同,这样会导致某些集合操作会出现问题。可以先将返回值转换为set进行集合操作

1.10 删除序列中相同元素并保持顺序

不保持排序的话,仅仅用set() 函数就可以解决。

首先要了解hashable类型yield函数,lambda函数

  1. hashable类型

    a.哈希表是在一个关键字和一个较大的数据之间建立映射的表,能使对一个数据序列的访问过程更加迅速有效。用作查询的关键字必须唯一且固定不变。

    b.immutable 属性,该属性指对象一经创建便不可修改。数据类型是integer,string,tuple都是不可更改的;list,dictionary,set是可更改的

    hashable ≈ imutable 可哈希 ≈ 不可变

    因此,immutable的对象可以作为一个固定不变的对象,适合作为哈希表的索引,因而它们是hashable的。

    *如果一个对象在其生命周期内,其哈希值从未改变(这需要一个__hash__()方法),并且可以与其他对象进行比较(这需要一个__eq__()或__cmp__()方法),那么这个对象就是可哈希的。哈希对象的相等意味着其哈希值的相等。

    哈希性使得对象可以用作dictionary键和set成员,因为这些数据结构在内部使用了哈希值。

    Python的所有不可变的内置对象都是可hashable的,但可变容器(如列表或字典)并非如此。对于用户定义的类的实例,默认情况下是可哈希的;它们都是不相等的,并且它们的哈希值都是id()*

  2. yield函数

    一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 _next()_)才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

    def fab(max): 
        n, a, b = 0, 0, 1 
        while n < max: 
            yield b 
            # print b 
            a, b = b, a + b 
            n = n + 1 
    >>> for n in fab(5): 
    ...     print n 
    ... 
    1 
    1 
    2 
    3 
    5
    
  3. lambda函数

匿名函数

lambda [arg1 [, agr2,.....argn]] : expression
1、单个参数的:
>>> g = lambda x : x ** 2
>>> print g(3)
9
2、多个参数的:
>>> g = lambda x, y, z : (x + y) ** z
>>> print g(1,2,2)
9

以上了解完毕后,开始处理删除序列相同元素并保持顺序

主要通过yield函数来实现顺序不变,

  1. 序列中元素是hashable的

    def dedupe(items):
        seen = set()
        for item in items:
            if item not in seen:
                yield item
                seen.add(item)
    

    输出

    >>> a = [1, 5, 2, 1, 9, 1, 5, 10]
    >>> list(dedupe(a))
    [1, 5, 2, 9, 10]
    >>>
    
  2. 序列中元素不是hashable的

    先将不可序列化的元素通过lambda函数转换为tuple类型可序列

    def dedupe(items, key=None):
        seen = set()
        for item in items:
            val = item if key is None else key(item)
            if val not in seen:
                yield item
                seen.add(val)
    

    输出

    >>> a = [ {'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]
    >>> list(dedupe(a, key=lambda d: (d['x'],d['y'])))
    [{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
    >>> list(dedupe(a, key=lambda d: d['x']))
    [{'x': 1, 'y': 2}, {'x': 2, 'y': 4}]
    >>>
    
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值