python高级编程1

1.如何在列表,字典,集合中根据条件筛选数据?

如:

过滤列表[3, 9, -1, 10, 20, -2...]中的负数

筛出字典{‘小明’:70, 'Jim':88,'Tom':98...}中值高于90的项

 筛出集合(2,3,5,7,8,12,23...)中能被3整除的元素

像第一种过滤列表中的负数,有一种通用的方法

data = [1,2,-1,-4,3,5,6]

result = []

for x in data:
    if x >= 0:
        result.append(x)

print result

在python中我们可以使用高级的工具,如:

列表 filter函数 filter(lambda x:x >=0, data)
列表解析 [x for x in data if x>=0]
字典 字典解析 {k : v for k, v in d.iteritems() if v > 90}
集合 集合解析 {x for x in s if x%3 ==0}

 

在列表中筛选大于等于零的方法:

第一种方式:

 

In [1]: from random import randint
In [2]: data = [randint(-10, 10)for _ in xrange(10)]

In [3]: data
Out[3]: [-8, 3, 6, 9, -1, 10, 3, 4, -7, -9]

In [4]: filter(lambda x: x>=0,data)
Out[4]: [3, 6, 9, 10, 3, 4]

 

 第二种方式:

In [5]: [x for x in data if x >= 0]
Out[5]: [3, 6, 9, 10, 3, 4]

 

比较两种方式哪种好

In [6]: timeit filter(lambda x: x>=0,data)
1000000 loops, best of 3: 1.22 µs per loop

In [7]: timeit [x for x in data if x >= 0]
1000000 loops, best of 3: 546 ns per loop

由此得出列表解析快出filter函数,但两者方式速度都高于上面的通用方法

 

 在字典中筛选元素

In [13]: d = {x: randint(60,100) for x in xrange(1,20)}

In [14]: d
Out[14]:
{1: 90,
 2: 91,
 3: 97,
 4: 77,
 5: 77,
 6: 86,
 7: 87,
 8: 92,
 9: 81,
 10: 91,
 11: 74,
 12: 80,
 13: 88,
 14: 96,
 15: 82,
 16: 83,
 17: 93,
 18: 66,
 19: 73}

In [15]: {k : v for k,v in d.iteritems() if v > 90}
Out[15]: {2: 91, 3: 97, 8: 92, 10: 91, 14: 96, 17: 93}

 

 

在集合中筛选符合条件的

In [16]: data
Out[16]: [-8, 3, 6, 9, -1, 10, 3, 4, -7, -9]

In [17]: s = set(data)

In [18]: s
Out[18]: {-9, -8, -7, -1, 3, 4, 6, 9, 10}

In [19]: {x for x in s if x % 3 == 0}
Out[19]: {-9, 3, 6, 9}

 

 

2.如何为元祖中的每个元素命名,提高程序的可读性

如:

学生管理系统中数据为固定格式:

(名字,年龄,性别,邮箱地址,...)

学生数量很大为了减小存储开销,对每个学生信息用元祖表示:

('Jim', 16, 'male', 'jim123@qq.com')

('Tom', 17, 'male', 'tom@qq.com')

...

访问时,我们使用索引访问,大量索引降低了可读性,如何解决这个问题呢?

如:

In [20]: student = ('Jim', 16, 'male', 'jim123@qq.com')

#name
In [22]: print student[0]
Jim

#age
In [23]: print student[1]
16

#sex
In [24]: print student[2]
male

#email
In [25]: print student[3]
jim123@qq.com

第一种方法可以定义常量,如:

In [26]: Name = 0

In [27]: Age = 1

In [28]: Sex = 2

In [29]: Email = 3
...
#Name,Age,Sex,Email = xrange(4)
In [
30]: student = ('Jim', 16, 'male', 'jim123@qq.com') In [32]: print student[Name] Jim In [33]: print student[Age] 16 ...

第二种方案:使用标准库中collections.namedtuple替对内置tuple

In [37]: from collections import namedtuple

In [38]: Student = namedtuple('Student', ['name', 'age', 'sex', 'email'])

In [39]: s = Student('Jim', 16, 'male', 'jim123@qq.com')

In [40]: s
Out[40]: Student(name='Jim', age=16, sex='male', email='jim123@qq.com')

In [41]: s2 =  Student(name='Jim', age=16, sex='male', email='jim123@qq.com')

In [42]: s2
Out[42]: Student(name='Jim', age=16, sex='male', email='jim123@qq.com')

In [43]: s.name
Out[43]: 'Jim'

In [44]: s.age
Out[44]: 16
...

 3.如何统计序列中元素的出现频度?

如:1.某随机序列[1,3,2,6,7,11,...]中,找到出现次数最高的3个元素,它们出现的次数是多少?

  2.对某英文文章的单词,进行词频统计,找到出现次数最高的10个单词,他们出现的次数是多少?

方法一.可以使用字典的方法

In [1]: from random import randint

In [2]: data = [randint(0,20) for _ in xrange(30)]

In [3]: data
Out[3]:
[10,
 19,
 13,
 13,
 4,
 5,
 15,
 3,
 4,
 0,
 8,
 17,
 19,
 3,
 18,
 3,
 19,
 4,
 14,
 13,
 3,
 8,
 2,
 18,
 7,
 17,
 9,
 7,
 13,
 4]

In [4]: dict1 = {}.fromkeys(data,0)

In [5]: for x in data:
   ...:     dict1[x] += 1
   ...:

In [6]: dict1
Out[6]:
{0: 1,
 2: 1,
 3: 4,
 4: 4,
 5: 1,
 7: 2,
 8: 2,
 9: 1,
 10: 1,
 13: 4,
 14: 1,
 15: 1,
 17: 2,
 18: 2,
 19: 3}

 

方法二.使用collections.Counter对象,将序列传入Counter的构造器,得到Counter对象是元素频度的字典,Counter.most_common(n)方法得到频度最高的n个元素的列表

In [9]: data1 = Counter(data)

In [10]: data1
Out[10]:
Counter({0: 1,
         2: 1,
         3: 4,
         4: 4,
         5: 1,
         7: 2,
         8: 2,
         9: 1,
         10: 1,
         13: 4,
         14: 1,
         15: 1,
         17: 2,
         18: 2,
         19: 3})


In [11]: data1.most_common(3)
Out[11]: [(3, 4), (4, 4), (13, 4)]

 

#统计英语文章单词
In [20]: import re

In [21]: txt = open('a.txt').read()

In [22]: txt
Out[22]: 'Anti Tracks is a complete solution to protect your privacy and enhance ....'

In [23]: re.split('\W+',txt)
Out[23]:
['Anti',
 'Tracks',
 'is',
 'a',
 'Tracks',
 'securely',
 ...})

In [26]: c.most_common()
Out[26]:
[('and', 5),
 ('Tracks', 4),
 ('your', 4),
 ('Anti', 4),
 ('erasing', 3),
 ('to', 3),
 ('computer', 2),
 ('privacy', 2),
 ('support', 2),
 ('more', 2),
 ...]

In [27]: c.most_common(10)
Out[27]:
[('and', 5),
 ('Tracks', 4),
 ('your', 4),
 ('Anti', 4),
 ('erasing', 3),
 ('to', 3),
 ('computer', 2),
 ('privacy', 2),
 ('support', 2),
 ('more', 2)]

 

4.如何根据字典中的值的大小,对字典中的项排序

如:某班英语成绩以字典的形式存储:

{'Limei':90, 'Tom':89,...}

根据成绩高低,计算成绩排名

方法一.利用zip将字典转换为元祖,再用sorted方法

In [29]: from random import randint

In [30]: d = {x:randint(70,100) for x in 'abcd'}

In [31]: d
Out[31]: {'a': 94, 'b': 85, 'c': 87, 'd': 94}

In [33]: zip(d.values(), d.keys())
Out[33]: [(94, 'a'), (87, 'c'), (85, 'b'), (94, 'd')]

#使用迭代方法节省空间
In [34]: zip(d.itervalues(), d.iterkeys())
Out[34]: [(94, 'a'), (87, 'c'), (85, 'b'), (94, 'd')]

In [35]: sorted(zip(d.itervalues(), d.iterkeys()))
Out[35]: [(85, 'b'), (87, 'c'), (94, 'a'), (94, 'd')]

 

方法二.传递sorted函数的key参数

In [36]: d.items()
Out[36]: [('a', 94), ('c', 87), ('b', 85), ('d', 94)]

In [37]: sorted(d.items(), key=lambda x :x[1] )
Out[37]: [('b', 85), ('c', 87), ('a', 94), ('d', 94)]

 

5.如何快速找到多个字典的公共键(key)?

如:足球联赛,每轮球员的进球统计:

  第一轮:{'梅西':2,'贝尔':2...}

  第二轮:{'梅西':1,'贝尔':1...}

  ...

  统计出前N轮,每场比赛都有进球的球员

方法一.将相同的键添加到列表中

In [38]: from random import randint, sample

#使用sample,产生随机进球的球员
In [39]: sample('abcdefg', randint(3,6))
Out[39]: ['d', 'c', 'b']

In [40]: s1 = {x:randint(1,3) for x in sample('abcdefg', randint(3,6))}

In [41]: s2 = {x:randint(1,3) for x in sample('abcdefg', randint(3,6))}

In [42]: s3 = {x:randint(1,3) for x in sample('abcdefg', randint(3,6))}

In [43]: s1
Out[43]: {'c': 3, 'd': 3, 'f': 1}

In [44]: s2
Out[44]: {'b': 2, 'd': 1, 'f': 1}

In [45]: s3
Out[45]: {'c': 2, 'd': 3, 'e': 2, 'f': 1, 'g': 3}

In [46]: result = []

In [47]: for key in s1:
    ...:     if key in s2 and key in s3:
    ...:         result.append(key)
    ...:

In [48]: result
Out[48]: ['d', 'f']

 

方法二.利用集合(set)的交集操作

1.使用字典的viewkeys()方法,得到一个字典keys的集合

In [49]: s1.viewkeys()
Out[49]: dict_keys(['c', 'd', 'f'])

In [50]: s2.viewkeys()
Out[50]: dict_keys(['b', 'd', 'f'])

In [51]: s3.viewkeys()
Out[51]: dict_keys(['c', 'e', 'd', 'g', 'f'])

In [53]: s1.viewkeys() & s2.viewkeys() & s3.viewkeys()
Out[53]: {'d', 'f'}

 

2.使用map函数,得到所有字典的keys集合

3.使用reduce函数,取所有字典的keys的集合的交集

In [55]: map(dict.viewkeys, [s1,s2,s3])
Out[55]:
[dict_keys(['c', 'd', 'f']),
 dict_keys(['b', 'd', 'f']),
 dict_keys(['c', 'e', 'd', 'g', 'f'])]

In [56]: reduce(lambda a,b:a&b, map(dict.viewkeys, [s1,s2,s3]))
Out[56]: {'d', 'f'}

 

6.如何让字典保持有序?

如:某答题比赛,对选手进行计时,答完题目后,用字典的形式保存,以便赛后按选手名查询成绩,(答题时间越短,成绩越优)

{‘Limei’:(2,43), 'Tom':(1,20),...}

比赛结束后,需要按照成绩打印名次,如何实现?

方法.使用collections中的OrderedDict替代内置Dict,依次将选手成绩存入OrderedDict

In [57]: from collections import OrderedDict

In [61]: d['a'] = (1,23)

In [62]: d['b'] = (2,25)

In [63]: d['c'] = (3,30)

In [64]: for key in d:
    ...:     print key
    ...:
a
b
c

 

问题代码

from time import time
from random import randint
from collections import OrderedDict

player = list('abcdef')
d = OrderedDict()
start = time()

for x in xrange(0,6):
    raw_input()
    p = player.pop(randint(0,5-x))
    end = time()
    print x+1, p, end-start
    d[p] = (x+1, end-start)

print '-'*20
    
for key in d:
    print key ,d[key]
View Code

 

7.如何实现用户的历史记录功能(最多n条)?

如:浏览器可以查看最近的访问过的网页

shell可以查看用户输入过的命令

现在我们制作一个猜数字游戏,来添加历史记录功能,显示用户最近猜测的数据

方法.使用容量为n的队列存储历史记录,使用标准库collections中的deque,它是一个双端循环队列,程序退出前,可以使用pickle将队列对象存入文件,再次运行程序时将其导入

from random import randint
from collections import deque 

N = randint(0,100)
history = deque([], 5)

def guess(k):
    if k == N:
        print 'right'

    if k < N:
        print '%s is less than N'% k

    if k > N:
        print '%s is greater than N'% k



while True:
    line = raw_input('please input a number:')
    if line.isdigit():
        k = int(line)
        history.append(k)
        if guess(k):
            break

    elif line == 'history' or line == 'h?':
        print list(history)
View Code

 

In [66]: from collections import deque

In [67]: q = deque([],3)

In [68]: q.append(3)

In [69]: q.append(4)

In [70]: q.append(8)

In [71]: q
Out[71]: deque([3, 4, 8])

In [72]: import pickle

In [73]: pickle.dump(q, open('a.txt','w'))

In [74]: open('a.txt').read()
Out[74]: 'ccollections\ndeque\np0\n((lp1\nI3\naI4\naI8\naI3\ntp2\nRp3\n.'

In [75]: q1 = pickle.load(open('a.txt'))

In [76]: q1
Out[76]: deque([3, 4, 8])

 

posted @ 2018-05-22 23:43  y-xs  阅读(504)  评论(0编辑  收藏  举报