13.Collections模块
一、实验目的
- Counter 类
- defaultdict 类
- namedtuple 类
二、知识要点
首先我们通过:
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
属性的初始值,默认值为None
,default_factory
属性值将作为字典的默认数据类型。所有剩余的参数与字典的构造方法相同,包括关键字参数。同样的功能使用 defaultdict
比使用 dict.setdefault
方法快。
3.namedtuple类
命名元组有助于对元组每个位置赋予意义,并且让我们的代码有更好的可读性和自文档性。你可以在任何使用元组地方使用命名元组。
三、实验内容
1.统计文件中某些单词的出现次数
在这里我们使用.collections.Counter
中的re类,使用most_common()
函数进行统计文章中出现次数最多的10个单词
- 代码:
from collections import Counter
import re
path = 'LICENSE.txt'
words = re.findall('\w+', open(path).read().lower())
print(Counter(words).most_common(10))
- 结果:
[('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()
方法,其返回的序列中,依照计数重复元素相同次数,元素顺序是无序的。
- 代码:
from collections import Counter
c = Counter(a=4, b=2, c=0, d=-2)
print(list(c.elements()))
- 结果:
['a', 'a', 'a', 'a', 'b', 'b']
2.使用defaultdict
创建列表
- 代码:
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())
- 结果:
dict_items([('zz', [99]), ('wyf', [98]), ('wcc', [745]), ('yxy', [666])])
即使 defaultdict对象不存在某个键,它会自动创建一个空列表。
3.使用namedtuple
定义命名元组
- 代码:
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)
- 结果:
10 20
10 20
10 20
四、实验结果
1.学生教师操作
写一个脚本使之具备如下的功能:
基类为Person
,Person
的两个派生类分别为Student
和Teacher
,在每个函数中除了需要有构造函数外,其他函数及说明如下:
-
Person.get_details
:返回包含人名的字符串 -
Person.get_grade
:返回0
-
Student.__init__
:返回 Student 对象,采用name, branch, year,grade
4 个参数 -
Student.get_details
:返回包含学生具体信息的字符串 -
Stduent.get_grade
:以Pass: X, Fail: X
来统计自己的成绩情况(A,B,C 为 Pass, 如果得了 D 就认为是 Fail) -
Teacher.__init__
:返回 Teacher 对象,采用字符串列表作为参数,包括name,papers,grade
3个参数 -
Teacher.get_details
:返回包含教师具体信息的字符串 -
Teacher.get_grade
:自动统计出老师班上学生的得分情况并按照频率的高低以 A: X, B: X, C: X, D: X 的形式打印出来
具体要求如下:
- 根据命令行中的第一个参数 teacher 或者 student 来判断最终输出的格式。
- 命令行中第二个输入的参数是需要统计的字符串
- 代码:
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()
- 结果:
(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