Python之codebook笔记

2020-01-16  本文已影响0人  鹊南飞_

1. 解压序列赋值给多个变量

任何的序列(或者可迭代对象)可以通过一个简单的赋值语句解压并赋值给多个变量。
唯一的前提就是变量的数量必须跟序列元素的数量是一样的

p = [4, 5, 6]
a, b, c = p
print(a, b, c)
4 5 6

2. 解压可迭代对象给多个变量

使用Python的星号(*)解决这个问题
解压出来的变量永远是列表类型

record = (1, 2, 3, 4, 5)
first, *number, end = record
print(first, number, end)
1 [2, 3, 4] 5

3. 保留最后N个元素

使用collections.deque

from collections import deque
# 构建一个固定长度为3的队列
q = deque(maxlen=3)
q.append(1)
q.append(2)
q.append(3)
q
deque([1, 2, 3])
q.append(4)
q
deque([2, 3, 4])

4. 保留最大或最小的N的元素

使用heapq模块的两个函数,nlargest()和nsmallest()

import heapq
nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))
print(max(nums))
print(min(nums))

[42, 37, 23]
[-4, 1, 2]
42
-4

# 可以接受关键字参数,用于更复杂的数据结构
portfolio = [
    {'name': 'IBM', 'shares': 100, 'price': 91.1},
    {'name': 'AAPL', 'shares': 50, 'price': 543.22},
    {'name': 'FB', 'shares': 200, 'price': 21.09},
    {'name': 'HPQ', 'shares': 35, 'price': 31.75},
    {'name': 'YHOO', 'shares': 45, 'price': 16.35},
    {'name': 'ACME', 'shares': 75, 'price': 115.65}
]
cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])
print(cheap)
print(expensive)

[{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]

当要查找的元素个数相对比较小的时候,heapq.nsmallest()和heapq.nlargest()是很合适的
如果只是想找唯一的最大或最小就使用max()和min()函数
如果N的大小和集合大小接近的时候,则使用切片操作会更快一点sorted(items)[:N]或者sorted(items)[-N:]

5. 实现一个优先级队列

使用heapq模块的heappush()和heappop()

import heapq

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0

    def push(self, item, priority):
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 1

    def pop(self):
        return heapq.heappop(self._queue)[-1]
class Item:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return 'Item({!r})'.format(self.name)


q = PriorityQueue()
q.push(Item('foo'), 1)
q.push(Item('bar'), 4)
q._queue

[(-4, 1, Item('bar')), (-1, 0, Item('foo'))]

q.pop()

Item('bar')

6. 字典中的键映射多个值

一个字典就是一个键对应一个单值的映射。
如果你想要一个值映射多个值,需要这多个值放到另外的容器中

d = {
    'a' : [1, 2, 3]
}
d

{'a': [1, 2, 3]}

d = {
    'a' : {1, 2, 3}
}
d

{'a': {1, 2, 3}}

# 或者可以使用collections.defaultdict
from collections import defaultdict
d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)
d

defaultdict(list, {'a': [1, 2], 'b': [4]})

d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)
d

defaultdict(set, {'a': {1, 2}, 'b': {4}})

7. 字典排序

使用collections模块OrderedDict类
在迭代的时候保存元素被插入时的顺序
注意,3.6 的 dict 是有序的,在此版本之前皆是无序

from collections import OrderedDict
d = OrderedDict()
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['aok'] = 4
for key in d:
    print(key, d[key])

foo 1
bar 2
spam 3
aok 4

d = {}
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['aok'] = 4
for key in d:
    print(key, d[key])

foo 1
bar 2
spam 3
aok 4

8. 字典的运算(求最大值,最小值,排序等等)

prices = {
    'ACME': 45.23,
    'AAPL': 612.78,
    'IBM': 205.55,
    'HPQ': 37.20,
    'FB': 10.75
}

直接使用max函数,是对字典的key值进行操作
可以使用zip函数将键和值反转过来
注意:zip()函数创建的是一个只能访问一次的迭代器

min_price = min(zip(prices.values(), prices.keys()))
max_price = max(zip(prices.values(), prices.keys()))
min_price, max_price

((10.75, 'FB'), (612.78, 'AAPL'))

9. 查找两字典的相同点

可以简单的使用字典的keys()或者items()方法返回结果上执行集合操作

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

b = {
    'w' : 1,
    'x' : 11,
    'y' : 2
}

a.keys() & b.keys()

{'x', 'y'}

a.items() & b.items()

{('y', 2)}

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

10. 删除序列相同元素并保持排序

def dedupe(items):
    seen = set()
    for item in items:
        if item not in seen:
            print('item is {}, seen is {}'.format(item, seen))
            yield item
            seen.add(item)

a = [1,3,4,5,6,1,3,5]
list(dedupe(a))

item is 1, seen is set()
item is 3, seen is {1}
item is 4, seen is {1, 3}
item is 5, seen is {1, 3, 4}
item is 6, seen is {1, 3, 4, 5}

[1, 3, 4, 5, 6]

def dedupe(items, key=None):
    seen = set()
    for item in items:
        val = item if key is None else key(item)
        print('item {} value {}'.format(item, val))
        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'])))

item {'x': 1, 'y': 2} value (1, 2)
item {'x': 1, 'y': 3} value (1, 3)
item {'x': 1, 'y': 2} value (1, 2)
item {'x': 2, 'y': 4} value (2, 4)

[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]

匿名函数: 将创建好的匿名函数通过一个变量去接收,使用变量去调用函数

简单使用set()方法构建一个集合,也可以实现消除重复元素,但是元素位置会被打乱

11. 命名切片

给切片命名,使得代码更加清晰可读
record = '....................100 .......513.25 ..........'
# 使用slice切片,并命名
SHARES = slice(20, 23)
PRICE = slice(31, 37)
cost = int(record[SHARES]) * float(record[PRICE])
cost

51325.0

12. 序列中出现次数最多的元素

collctions.Counter类,里面的most_common()
words = [
    'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
    'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
    'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
    'my', 'eyes', "you're", 'under'
]
from collections import Counter
word_counts = Counter(words)
# 出现频率最高的3个单词
top_three = word_counts.most_common(3)
print(top_three)

[('eyes', 8), ('the', 5), ('look', 4)]

13. 通过某个关键字排序一个字典列表

operator.itemgetter函数
rows = [
    {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
    {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
    {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
    {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
from operator import itemgetter
rows_by_fname = sorted(rows, key=itemgetter('fname'))
rows_by_uid = sorted(rows, key=itemgetter('uid'))
print(rows_by_fname)
print(rows_by_uid)

[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]
[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]

min(rows, key = itemgetter('uid'))

{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}

14. 排序不支持原生比较的对象

operator.attagetter()函数
class User:
    def __init__(self, user_id):
        self.user_id = user_id

    def __repr__(self):
        return 'User({})'.format(self.user_id)
    
users = [User(23), User(3), User(99)]
from operator import attrgetter
sorted(users, key=attrgetter('user_id'))

[User(3), User(23), User(99)]

15. 通过某个字段将记录分组

itertools.groupby()

16. 过滤序列元素

最简单的办法是列表推导

17. 从字典中提取子集

最简单的办法是字典推导
prices = {
    'ACME': 45.23,
    'AAPL': 612.78,
    'IBM': 205.55,
    'HPQ': 37.20,
    'FB': 10.75
}
p1 = {key: value for key, value in prices.items() if value > 200}
print(p1)

{'AAPL': 612.78, 'IBM': 205.55}

tech_names = {'AAPL', 'IBM', 'HPQ'}
p2 = {key: value for key, value in prices.items() if key in tech_names}
print(p2)

{'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.2}

18. 映射名称到序列元素

collections.namedtuple()函数

19. 转换并同时计算数据

nums = [1, 2, 3, 4, 5]
s = sum(x * x for x in nums)
s

55

s = sum((x * x for x in nums)) # 显示的传递一个生成器表达式对象
s=  sum((x * x for x in nums) # 更加优雅的实现方式,省略了括号

portfolio = [
    {'name':'GOOG', 'shares': 50},
    {'name':'YHOO', 'shares': 75},
    {'name':'AOL', 'shares': 20},
    {'name':'SCOX', 'shares': 65}
]
min_shares = min(s['shares'] for s in portfolio)
min_shares

20

20. 合成多个字典或映射

使用collections.ChainMap类
上一篇下一篇

猜你喜欢

热点阅读