13.Collections模块

collections 是 Python 内建的一个集合模块,提供了许多有用的集合类。

一、实验目的

  • Counter 类
  • defaultdict 类
  • namedtuple 类

二、知识要点

首先我们通过:

1
import collections

导入Collections模块,这个模块实现了一些很好的数据结构,能够解决各种实际问题。

1.Counter类

在这里我们需要先来了解一下哈希值的概念,通常来说,所有Python内置的不可变对象都是可哈希的,同时,可变容器都是不可哈希的,有关可变对象与不可变对象在8.函数的对象中(可更改、不可更改对象)。官方文档对于哈希(hashable)的解释是这样的:

如果一个对象在其生命周期内有一个固定不变的哈希值 (这需要__hash__()方法) 且可以与其他对象进行比较操作 (这需要__eq__()方法) ,那么这个对象就是可哈希对象 (hashable) 。可哈希对象必须有相同的哈希值才算作相等。
由于字典 (dict) 的键 (key) 和集合 (set) 内部使用到了哈希值,所以只有可哈希 (hashable) 对象才能被用作字典的键和集合的元素。
所有python内置的不可变对象都是可哈希的,同时,可变容器 (比如:列表 (list) 或者字典 (dict) ) 都是不可哈希的。用户自定义的类的实例默认情况下都是可哈希的;它们跟其它对象都不相等 (除了它们自己) ,它们的哈希值来自id()方法。

较为详细的解释参考文章:简书:聊一聊Python中的hashable和immutable

Counter 是一个有助于 hashable 对象计数的 dict 子类。它是一个无序的集合,其中 hashable 对象的元素存储为字典的键,它们的计数存储为字典的值,计数可以为任意整数,包括零和负数。

2.defaultdict类

defaultdict 是内建 dict类的子类,它覆写了一个方法并添加了一个可写的实例变量。其余功能与字典相同。defaultdict() 第一个参数提供了 default_factory 属性的初始值,默认值为Nonedefault_factory 属性值将作为字典的默认数据类型。所有剩余的参数与字典的构造方法相同,包括关键字参数。同样的功能使用 defaultdict 比使用 dict.setdefault 方法快。

3.namedtuple类

命名元组有助于对元组每个位置赋予意义,并且让我们的代码有更好的可读性和自文档性。你可以在任何使用元组地方使用命名元组。

三、实验内容

1.统计文件中某些单词的出现次数

在这里我们使用.collections.Counter中的re类,使用most_common()函数进行统计文章中出现次数最多的10个单词

  • 代码:
1
2
3
4
5
from collections import Counter
import re
path = 'LICENSE.txt'
words = re.findall('\w+', open(path).read().lower())
print(Counter(words).most_common(10))
  • 结果:
1
[('the', 277), ('of', 160), ('or', 146), ('and', 129), ('in', 112), ('to', 97), ('software', 95), ('this', 95), ('any', 76), ('1', 71)]
  • 函数解释:

re.findall:

对 string 返回一个不重复的 pattern 的匹配列表, string 从左到右进行扫描,匹配按找到的顺序返回。如果样式里存在一到多个组,就返回一个组合列表;就是一个元组的列表(如果样式里有超过一个组合的话)。空匹配也会包含在结果里。

使用Counter对象中的element()方法,其返回的序列中,依照计数重复元素相同次数,元素顺序是无序的。

  • 代码:
1
2
3
4
from collections import Counter

c = Counter(a=4, b=2, c=0, d=-2)
print(list(c.elements()))
  • 结果:
1
['a', 'a', 'a', 'a', 'b', 'b']
2.使用defaultdict创建列表
  • 代码:
1
2
3
4
5
6
7
from collections import defaultdict

s = [('zz', 99), ('wyf', 98), ('wcc', 745), ('yxy', 666)]
d = defaultdict(list)
for k, v in s:
d[k].append(v)
print(d.items())
  • 结果:
1
dict_items([('zz', [99]), ('wyf', [98]), ('wcc', [745]), ('yxy', [666])])
即使 defaultdict对象不存在某个键,它会自动创建一个空列表。
3.使用namedtuple定义命名元组
  • 代码:
1
2
3
4
5
6
7
8
from collections import namedtuple

Point = namedtuple('Point', ['x', 'y']) # 定义命名元组
p = Point(10, y=20) # 创建一个对象
print(p.x, p.y)
print(p[0], p[1]) # 像普通元组那样访问元素
x, y = p # 元组拆封
print(x, y)
  • 结果:
1
2
3
10 20
10 20
10 20

四、实验结果

1.学生教师操作

写一个脚本使之具备如下的功能:
基类为PersonPerson的两个派生类分别为StudentTeacher,在每个函数中除了需要有构造函数外,其他函数及说明如下:

  • Person.get_details:返回包含人名的字符串
  • Person.get_grade:返回0
  • Student.__init__:返回 Student 对象,采用name, branch, year,grade4 个参数
  • Student.get_details:返回包含学生具体信息的字符串
  • Stduent.get_grade:以Pass: X, Fail: X来统计自己的成绩情况(A,B,C 为 Pass, 如果得了 D 就认为是 Fail)
  • Teacher.__init__:返回 Teacher 对象,采用字符串列表作为参数,包括name,papers,grade3个参数
  • Teacher.get_details:返回包含教师具体信息的字符串
  • Teacher.get_grade:自动统计出老师班上学生的得分情况并按照频率的高低以 A: X, B: X, C: X, D: X 的形式打印出来

具体要求如下:

  1. 根据命令行中的第一个参数 teacher 或者 student 来判断最终输出的格式。
  2. 命令行中第二个输入的参数是需要统计的字符串
  • 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import sys
from collections import Counter


class Person(object):
def __init__(self, name):
self.name = name

def get_details(self):
return self.name

def get_grade(self):
return 0


class Student(Person):
def __init__(self, name, branch, year, grade):
Person.__init__(self, name)
self.branch = branch
self.year = year
self.grade = grade

def get_details(self):
return "{} studies {} and is in {} year.".format(self.name, self.branch, self.year)

def get_grade(self):
common = Counter(self.grade).most_common(4)
pass_s = 0
fail_s = 0
for item in common:
if item[0] != 'D':
pass_s += item[1]
else:
fail_s += item[1]
print("pass: {}, Fail: {}".format(pass_s, fail_s))


class Teacher(Person):
def __init__(self, name, papers, grade):
Person.__init__(self, name)
self.papers = papers
self.grade = grade

def get_details(self):
return "{} teaches {}".format(self.name, ','.join(self.papers))

def get_grade(self):
s = []
common = Counter(self.grade).most_common(4)
for i, j in common:
s.append("{}:{}".format(i, j))
print(', '.join(s))


person = Person('Sachin')
if sys.argv[1] == 'student':
student1 = Student("Kushal", "CSE", 2005, sys.argv[2])
student1.get_grade()
else:
teacher1 = Teacher("Prachad", ['C', 'C++'], sys.argv[2])
teacher1.get_grade()
  • 结果:
1
2
3
4
5
(venv) F:\NewPython\13>python teacher_grade.py teacher ABCCBABAAD
A:4, B:3, C:2, D:1

(venv) F:\NewPython\13>python teacher_grade.py student ABBDDCBADA
pass: 7, Fail: 3

下一篇:14.PEP8代码风格指南
上一篇:12.模块
目 录:Python学习

本文标题:13.Collections模块

文章作者:小哲

发布时间:2020年03月15日 - 01:48

最后更新:2020年03月30日 - 11:40

原始链接: 点击复制原始链接

许可协议: 协议-转载请保留原文链接及作者