zoukankan      html  css  js  c++  java
  • PythonCookbook读书笔记

    第一章 数据结构和算法

    1.1 将序列分解为单独的变量

    适用于元组、列表、字符串等。只要是可迭代的对象,都可以执行分解操作。唯一的要求是变量的总数和结构要与序列相同。

    1.2 从任意长度的可迭代对象中分解元素

    “*表达式”

    以下代码中使用的“*args”,如果去掉*,是会报错的。

    records = [('foo',1,2),('bar','hello'),('foo',3,4)]
    for tag,*args in records:
        print(tag,*args)

    拆分操作,和split结合使用,会实现非常好用的功能:

    line = 'nobody:*:-2:-2:Unprivileged User:/Var/empty:/usr/bin/false'
    uname,*fields,homedir,sh = line.split(':')

    1.3 保留最后N个元素

    下边一段代码还不是特别理解,对生成器比较生疏。

    from collections import deque
    
    def search(lines,pattern,history):
        previous_lines = deque(maxlen=history)
        for line in lines:
            if pattern in line:
                yield line,previous_lines
            previous_lines.append(line)
            
    if __name__ == '__main__':
        with open('somefile.txt') as f:
            for line,prevlines in search(f,'Python',5):
                for pline in prevlines:
                    print(pline,end='')
                print(line,end='')
                print('-'*20)

    deque(maxlen=N)创建一个固定长度的队列,有新元素添加时,会自动删除最老的记录。

    不指定长度的时候,创建一个无界限的队列:

    from collections import deque
    q = deque()
    q.append(1)
    q.append(2)
    q.append(3)
    print(q)
    
    q.append(4)#右边添加元素
    q.appendleft(0)#左边添加元素
    print(q)
    q.pop()#删除最右边元素
    print(q)
    q.popleft()#删除左边元素
    print(q)

    1.4 找到最大或最小的N个元素

     heapq模块中的nlargest和nsmallest函数:

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

    提供一个参数key,使其工作在更复杂的结构上:

    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'])
    print(cheap)
    expensive = heapq.nlargest(3,portfolio,key=lambda s: s['price'])
    print(expensive)

    如果正在寻找最大或者最小的N个元素,且同集合中元素的总数目相比,N很小,那么可以使用以下函数(性能更好):为什么?

    nums = [1,8,2,23,7,-4,16,23,42,37,2]
    heap = list(nums)
    
    #找到第3小的元素
    heapq.heappop(heap)
    heapq.heappop(heap)
    heapq.heappop(heap)

    当所要寻找的元素数量相对较小时,nlargest和nsmallest函数才是最适用的。如果只是简单寻找最大和最小值,那么max和min函数会更快。如果N和集合本身大小差不多,通常更快的方法是先对集合排序,然后进行切片操作( sorted(items)[:N] 和sorted(items)[-N:] )。

    1.5 实现优先级队列(暂时搁置)

    1.6 在字典中将键映射到多个值上

    一键多值字典,可以使用collections模块中的defaultdict类:

    from collections import defaultdict
    
    d = defaultdict(list)
    d['a'].append(1)
    d['a'].append(2)
    d['b'].append(3)
    print(d)
    
    d = defaultdict(set)
    d['a'].add(1)
    d['a'].add(2)
    d['b'].add(3)
    print(d)

    使用列表还是集合,取决于实际需要,注重顺序,则使用列表;希望去除重复值,则使用集合。

    以上方法会自动创建字典表项(什么东西)以待稍后访问,也可以在普通字典上使用setdefault方法:

    d = {}
    d.setdefault('a',[]).append(1)
    d.setdefault('a',[]).append(2)
    d.setdefault('b',[]).append(3)
    print(d)

    1.7 让字典保持有序

    collections模块中的OrderedDict类可使字典在迭代的时候保持严格按照元素初始添加的时候的顺序:

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

    因为对字典的特性了解的还不够深,所以对这种好处的理解不是很深刻。

    json编码时严格控制字段的顺序,就可以使用此种方法:

    import json
    json.dumps(d)

    OrderedDict内部维护了一个双向链表,根据元素添加的顺序来排列键的位置,大小是普通字典的两倍多,在使用的时候就要衡量其带来的好处和增加的额外内存开销的缺点。

     1.8 与字典有关的计算问题

    zip()会将字典的键和值反转过来,然后进行一些计算,比如求最值、排序等:

    prices = {'ACME':45.23,
              'AAPL':612.78,
              'IBM':205.55,
              'HPQ':27.20,
              'FB':10.75}
    min_prices = min(zip(prices.values(),prices.keys()))
    max_prices = max(zip(prices.values(),prices.keys()))
    sorted_prices = sorted(zip(prices.values(),prices.keys()))

    zip创建一个迭代器(?),内容只能被消费一次,以下代码会报错:

    prices_and_names = zip(prices.values(),prices.keys())
    print(min(prices_and_names))
    print(max(prices_and_names))

    在字典上执行常规的数据操作(例如min(prices)),结果是只处理键,而不处理值;如果想利用字典的values()方法解决这个问题,结果只看到值得结果看不到对应的键的信息。

    zip将字典的键值对反转为值键对,在这样的元组上进行比较时,值会先进行比较,然后再比较键。如果有多个键对应着相同的值,这时候key就将称为判定结果的依据。

    1.9 在两个字典中寻找相同点

     通过keys()或者items()执行集合操作即可实现:

    a = {'x':1,'y':2,'z':3}
    b = {'w':10,'x':11,'y':2}
    a.keys() & b.keys()
    a.keys() - b.keys()
    a.items() & b.items()
    
    c = {key:a[key] for key in a.keys() - {'z','w'}}

    注意,对于集合的values()方法不支持集合操作。可以将值转化为集合后来操作。

    1.10 从序列中移除重复项且保持元素间顺序不变

    1.11 对切片命名

    从字符串的固定位置取出具体的数据:

    record = '....................100.......513.25..........'
    cost = int(record[20:23]) * float(record[30:36])

    避免使用许多神秘难懂的硬编码索引,使用切片命名:

    shares = slice(20,23)
    prices = slice(30,36)
    cost = int(record[shares]) * float(record[prices])

    slice对象实例s可以通过s.start, s.stop, s.step属性获取实例对象的信息:

    a = slice(2,40,5)
    a.start
    a.stop
    a.step

    可以通过使用indices(size)方法将切片映射到特定大小的序列上,会返回一个(start, stop, step)元组。

    s = 'HelloWorld'
    a.indices(len(s))
    for i in range(*a.indices(len(s))):
        print(s[i])

    range参数里的*号是做什么的呢?

    1.12 找出序列中出现次数最多的元素

     collections模块中的Counter类:

    words = ["twinkle", "twinkle", "little", "star", 
             "how", "i", "wonder", "what", "you", "are", 
             "up", "above", "the", "world", "so", "high",  
             "like", "a", "diamond", "in", "the", "sky",  
             "twinkle", "twinkle", "little", "star", 
             "how", "i", "wonder", "what", "you", "are"]
    
    from collections import Counter
    wordsCounts = Counter(words)
    top_three = wordsCounts.most_common(3)

    在底层实现中,Counter是一个字典,在元素和出现次数之间做了映射,我们可以通过以下方式查看某个单词出现的次数:

    print(wordsCounts["i"])

    使用update方法增加计数:

    morewords = ["like", "a", "diamond", "in", "the", "sky"]
    wordsCounts.update(morewords)
    print(wordsCounts)

    Counter对象可以同各种数学运算操作结合起来:

    a = Counter(words)
    b = Counter(morewords)
    c = a+b
    print(c)
    d = a-b
    print(d)

    1.13 通过公共键对字典列表排序

     根据一个或者多个字典中的值对列表排序,利用operator模块中的itemgetter函数:

    rows = [{"fname":"Brain" , "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'))
    print(rows_by_fname)
    
    rows_by_uid = sorted(rows, key=itemgetter('uid'))
    print(rows_by_uid)

    itemgetter函数可以接受多个参数:

    rows_by_lfname = sorted(rows, key=itemgetter('lname', 'fname'))
    print(rows_by_lfname)

    有时候用lambda表达式取代itemgetter()的功能:

    rows_by_fname = sorted(rows, key=lambda r: r['fname'])
    print(rows_by_fname)

    除了可以使用sorted()函数之外,还可以用与min()与max()函数。

    1.14 对不原生支持比较操作的对象排序

  • 相关阅读:
    成熟到优秀的瓶颈问题
    今天我们为什么不成功
    将HTML标签变为小写
    2010世界杯 排阵型 猜比分
    又一款 jQuery 头图切换形式
    整理下工作环境的相应资源
    prototype 的ajax
    即时点选的菜单
    如何禁止一个输入框输入
    基于jQuery的仿FLASH 菜单
  • 原文地址:https://www.cnblogs.com/dennis-liucd/p/8057161.html
Copyright © 2011-2022 走看看