Python实例(一):序列操作

来源:互联网 发布:美剧黑中国 知乎 编辑:程序博客网 时间:2024/06/02 22:19
#!/usr/bin/env python# -*- coding: utf-8 -*-# @Author  : Peidong# @Site    : # @File    : N_variables.py# @Software: PyCharm# 解压序列赋值给多个变量# 1.1 问题:现在有一个包含N 个元素的元组或者是序列,怎样将它里面的值解压后同时赋值给N 个变量?# 解答:任何的序列(或者是可迭代对象) 可以通过一个简单的赋值语句解压并赋值给多个变量。唯一的前提就是变量的数量必须跟序列元素的# 数量是一样的。p = (4,5)x,y = pprint(x,y)data = ['ACME', 50, 91.1, (2012, 12, 21)]name, shares, price, date = dataprint(name, shares, price, date)name, shares, price, (year, mon, day) = dataprint(name, shares, price, (year, mon, day))# 这种解压赋值可以用在任何可迭代对象上面,而不仅仅是列表或者元组。# 包括字符串,文件对象,迭代器和生成器。s = 'Hello'a, b, c, d, e = sprint(a)# 部分解析data = [ 'ACME', 50, 91.1, (2012, 12, 21) ]_, shares, price, _ =dataprint(shares)# 1.2 问题:如果一个可迭代对象的元素个数超过变量个数时,会抛出一个ValueError 。那么# 怎样才能从这个可迭代对象中解压出N 个元素出来?# 解决:Python 的星号表达式可以用来解决这个问题# eg:统计下家庭作业的平均成绩,但是排除掉第一个和最后一个分数def drop_first_last(grades):    first, *middle, last = grades    return avg(middle)record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')name, email, *phone_numbers = recordprint(phone_numbers)# 星号表达式也能用在列表的开始部分*trailing, current = [10, 8, 7, 1, 9, 5, 10, 3]print(trailing,   current)# 星号表达式在迭代元素为可变长元组的序列records = [('foo', 1, 2),('bar', 'hello'),('foo', 3, 4),]def do_foo(x, y):    print('foo', x, y)def do_bar(s):    print('bar', s)for tag, *args in records:    if tag == 'foo':        do_foo(*args)    elif tag == 'bar':        do_bar(*args)# 1.3 问题: 保留最后N个元素# 解决: 使用collections.deque# 使用deque(maxlen=N) 构造函数会新建一个固定大小的队列。当新的元素加入并# 且这个队列已满的时候,最老的元素会自动被移除掉from collections import dequeq = deque(maxlen= 3)q.append(1)q.append(2)q.append(3)print(q)q.append(4)q.append(5)print(q)# deque 类可以被用在任何你只需要一个简单队列数据结构的场合。如# 果你不设置最大队列大小,那么就会得到一个无限大小队列,你可以在队列的两端执# 行添加和弹出元素的操作p = deque()p.append(1)p.append(2)p.append(3)print(p)# 在队列左边添加元素p.appendleft(4)print(p)# 弹出左边元素print(p.popleft())print(p)# 1.4 查找最大或最小的N个元素# 问题: 怎么从一个集合中获得最大或最小的N个元素列表# 解决:heapq 模块有两个函数:nlargest() 和nsmallest() 可以完美解决这个问import heapqnums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]print(heapq.nlargest(3, nums)) # 最大的三个print(heapq.nsmallest(3, nums)) # 最小的三个# 更复杂的数据结构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}]# price为关键字查找cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])print(cheap)expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])print(expensive)# 堆数据结构最重要的特征是heap[0] 永远是最小的元素。并且剩余的元素可以很# 容易的通过调用heapq.heappop() 方法得到,该方法会先将第一个元素弹出来,然后# 用下一个最小的元素来取代被弹出元素(这种操作时间复杂度仅仅是O(log N),N 是# 堆大小)# 当要查找的元素个数相对比较小的时候,函数nlargest() 和nsmallest() 是很# 合适的。如果你仅仅想查找唯一的最小或最大(N=1) 的元素的话,那么使用min() 和# max() 函数会更快些。类似的,如果N 的大小和集合大小接近的时候,通常先排序这# 个集合然后再使用切片操作会更快点( sorted(items)[:N] 或者是sorted(items)[-# N:] )。需要在正确场合使用函数nlargest() 和nsmallest() 才能发挥它们的优势(如果# N 快接近集合大小了,那么使用排序操作会更好些)。# 1.5 字典中的键映射多个值# 问题:怎样实现一个键对应多个值的字典(也叫multidict )?# 解决:一个字典就是一个键对应一个单值的映射。如果你想要一个键映射多个值,那么你# 就需要将这多个值放到另外的容器中,比如列表或者集合里面d = { 'a': [1, 2, 3], 'b': [2, 3, 4, 5] }print(d)# 解决2:使用collections 模块中的defaultdict 来构造这样的字典from collections import defaultdictd = defaultdict(list)d['a'].append(1)d['a'].append(2)d['b'].append(3)print(d)# 1.6 字典排序# 问题:创建一个字典,并且在迭代或序列化这个字典的时候能够控制元素的顺序。# 解决:为了能控制一个字典中元素的顺序, 可以使用collections 模块中的# OrderedDict 类。在迭代操作的时候它会保持元素被插入时的顺序from collections import OrderedDictdef ordered_dict():    d = OrderedDict()    d['foo'] = 1    d['bar'] = 2    d['spam'] = 3    d['grok'] = 4    for key in d:        print(key, d[key])ordered_dict()# OrderedDict 内部维护着一个根据键插入顺序排序的双向链表。每次当一个新的元# 素插入进来的时候,它会被放到链表的尾部。对于一个已经存在的键的重复赋值不会# 改变键的顺序。# 1.7 字典的运算# 问题:怎样在数据字典中执行一些计算操作(比如求最小值、最大值、排序等等)?# 解决:通常需要使用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()))print(min_price)max_price = max(zip(prices.values(), prices.keys()))print(max_price)# 可以使用zip() 和sorted() 函数来排列字典数据prices_sorted = sorted(zip(prices.values(), prices.keys()))print(prices_sorted)#执行这些计算的时候,需要注意的是zip() 函数创建的是一个只能访问一次的迭代器# 1.8 序列中出现次数最多的元素# 问题:怎样找出一个序列中出现次数最多的元素?# 解决:collections.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 Counterword_counts = Counter(words)# 出现频率最高的3 个单词top_three = word_counts.most_common(3)print(top_three)# 作为输入, Counter 对象可以接受任意的hashable 序列对象。在底层实现上,一# 个Counter 对象就是一个字典,将元素映射到它出现的次数上。# 1.9 通过某个关键字排序一个字典列表# 根据某个或某几个字典字段来排序这个列表# 使用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'))# 根据id排序rows_by_uid = sorted(rows, key=itemgetter('uid'))print(rows_by_fname)print(rows_by_uid)# 根据多个关键字排序rows_by_lfname = sorted(rows, key=itemgetter('lname','fname'))print(rows_by_lfname)# 1.10 通过某个字段将记录分组# 问题: 某个特定的字段比如date 来分组迭代访问# 解决:itertools.groupby() 函数对于这样的数据分组操作非常实用rows = [   {'address': '5412 N CLARK', 'date': '07/01/2012'},   {'address': '5148 N CLARK', 'date': '07/04/2012'},   {'address': '5800 E 58TH', 'date': '07/02/2012'},   {'address': '2122 N CLARK', 'date': '07/03/2012'},   {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},   {'address': '1060 W ADDISON', 'date': '07/02/2012'},   {'address': '4801 N BROADWAY', 'date': '07/01/2012'},   {'address': '1039 W GRANVILLE', 'date': '07/04/2012'},]from operator import itemgetterfrom itertools import groupby# 先按日期进行排序rows.sort(key=itemgetter('date'))# Iterate in groups 然后根据日期分组for date, items in groupby(rows, key=itemgetter('date')):    print(date)    for i in items:        print(' ', i)# groupby() 函数扫描整个序列并且查找连续相同值(或者根据指定key 函数返回值# 相同) 的元素序列。在每次迭代的时候,它会返回一个值和一个迭代器对象,这个迭代# 器对象可以生成元素值全部等于上面那个值的组中所有对象。# 一个非常重要的准备步骤是要根据指定的字段将数据排序。因为groupby() 仅仅# 检查连续的元素,如果事先并没有排序完成的话,分组函数将得不到想要的结果。# 1.11 从字典中提取子集prices = {   'ACME': 45.23,   'AAPL': 612.78,   'IBM': 205.55,   'HPQ': 37.20,   'FB': 10.75}# Make a dictionary of all prices over 200p1 = {key: value for key, value in prices.items() if value > 200}print(p1)
原创粉丝点击