StandardLibrary - Collections对象类型(计数器,双向队列,默认字典,有序字典,可命名元组)

2021年9月26日 3点热度 0条评论 来源: 开码牛

 

1.Collections对象类型(计数器,双向队列,默认字典,有序字典,可命名元组)

Python中的基本数据结构有list,dict,tuple,set。

Python还有一个功能比较强大的包collections,提供专用的数据结构,

collections的常用类型有:

计数器(Counter)

双向队列(deque)

默认字典(defaultdict)

有序字典(OrderedDict)

可命名元组(namedtuple)

 

(1)Counter

Counter作为字典的一个子类用来进行hashtable计数,将元素进行数量统计、计数后返回一个字典,键值为元素:值为元素个数

from collections import *

s = 'abcbcaccbbad'  

l = ['a','b','c','c','a','b','b']  

d = {'2': 3, '3': 2, '17': 2}  

# Counter 获取各元素的个数,返回字典  

print(Counter(s))   # Counter({'c': 4, 'b': 4, 'a': 3,'d': 1})  

print(Counter(l))   # Counter({'b': 3, 'a': 2, 'c': 2})  

print(Counter(d))   # Counter({3: 3, 2: 2, 17: 2})  

 

most_common

# most_common(int) 按照元素出现的次数进行从高到低的排序,返回前n个元素的字典  

m1 = Counter(s)  

print(m1)                  # Counter({'c': 4, 'b': 4, 'a': 3, 'd': 1})  

print(m1.most_common(3))  # [('c', 4), ('b', 4), ('a', 3)]  

 

elements

# elements 返回经过计数器Counter后的元素,返回的是一个迭代器  

e1 = Counter(s)  

print(''.join(sorted(e1.elements())))  # aaabbbbcccc  

e2 = Counter(d)  

print(sorted(e2.elements()))  # ['17', '17', '2', '2', '2', '3', '3'] 字典返回value个key  

 

update

# update 和set集合的update一样,对集合进行并集更新  

u1 = Counter(s)  

u1.update('123a')  

print(u1)  # Counter({'c': 4, 'b': 4, 'a': 4, 'd': 1, '2': 1, '3': 1, '1': 1})  

 

substract

# substract 和update类似,只是update是做加法,substract做减法,从另一个集合中减去本集合的元素,  

sub1 = 'which'  

sub2 = 'whatw'  

subset = Counter(sub1)  

print(subset)   # Counter({'h': 2, 'i': 1, 'c': 1, 'w': 1})  

subset.subtract(Counter(sub2))  

print(subset)   # Counter({'c': 1, 'i': 1, 'h': 1, 'a': -1, 't': -1, 'w': -1}) sub1中的h变为2,sub2中h为1,减完以后为1  

 

iteritems

与字典dict的items类似,返回由Counter生成的字典的所有item,只是在Counter中此方法返回的是一个迭代器,而不是列表

iterkeys

与字典dict的keys方法类似,返回由Counter生成的字典的所有key,只是在Counter中此方法返回的是一个迭代器,而不是列表

itervalues

与字典dict的values方法类似,返回由Counter生成的字典的所有value,只是在Counter中此方法返回的是一个迭代器,而不是列表

 

2.deque

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈.

>>> from collections import deque

>>> q = deque(['a', 'b', 'c'])

>>> q.append('x')

>>> q.appendleft('y')

>>> q

deque(['y', 'a', 'b', 'c', 'x'])

eque 包含在文件_collections.py中,属于高性能的数据结构之一.可以从两端添加和删除元素,常用的结构是它的简化版。

deque:生deque对象

str1 = 'abc123cd'  

dq = deque(str1)  

print(dq)        # deque(['a', 'b', 'c', '1', '2', '3', 'c', 'd'])  

 

appendleft:队列右边添加元素

deque:队列左边添加元素

dq = deque('abc123')  

dq.append('right')  

dq.appendleft('left')  

print(dq) # deque(['left', 'a', 'b', 'c', '1', '2', '3', 'right'])  

 

clear 清空队列中的所有元素

count(value)  返回队列中包含value的个数,结果类型为 integer

extend 队列右边扩展,可以是列表、元组或字典,如果是字典则将字典的key加入到deque

extendleft  同extend, 在左边扩展

dq = deque('abc123')  

dq.extend({1:10,2:20})  

dq.extendleft('L')  

print(dq) # deque(['L', 'a', 'b', 'c', '1', '2', '3', 1, 2]) 

 

pop 移除并且返回队列右边的元素

popleft 移除并且返回队列左边的元素

remove(value) 移除队列第一个出现的元素(从左往右开始的第一次出现的元素value)

reverse  队列的所有元素进行反转

dq.reverse()

print(dq)

#结果:deque(['3', '2', '1', 'c', 'b', 'a'])

rotate(n) 对队列的数进行移动,若n<0,则往左移动即将左边的第一个移动到最后,移动n次,n>0 往右移动

dq = deque([1,2,3,4,5])  

dq.rotate(-1) # 左移,1往左移动一位到5后面  

print(dq)  

 

3.defaultdict

默认字典,是字典的一个子类,继承有字典的方法和属性,默认字典在进行定义初始化的时候可以指定字典值得默认类型:

import collections

dic = collections.defaultdict(dict)  

dic['k1'].update({'k2':'aaa'})  

print(dic)  

我们看上面的例子,字典dic在定义的时候就定义好了值为字典类型,虽然现在字典中还没有键值 k1,但仍然可以执行字典的update方法. 这种操作方式在传统的字典类型中是无法实现的,必须赋值以后才能进行值得更新操作,否则会报错。

我看看一下传统的字典类型

b = dict()  

b['k1'].append('2')  

# TypeError: 'type' object is not iterable  

 

4.OrderedDict 

OrderDict叫做有序字典,也是字典类型(dict)的一个子类,是对字典的一个补充。 前面我们说过,字典类型是一个无序的集合,如果要想将一个传统的字典类型进行排序一般会怎么做了,我们可能会将字典的键值取出来做排序后在根据键值来进行有序的输出,我们看下面的一个例子:

# 定义传统字典  

dic1 = dict()  

# 按顺序添加字典内容  

dic1['a'] = '123'  

dic1['b'] = 'jjj'  

dic1['c'] = '394'  

dic1['d'] = '999'  

print(dic1)    # 结果: {'a': '123', 'c': '394', 'b': 'jjj', 'd': '999'}  

# 排序  

dic1_key_list = []  

for k in dic1.keys():  

    dic1_key_list.append(k)  

dic1_key_list.sort()  

for key in dic1_key_list:  

    print('dic1字典排序结果 %s:%s' %(key,dic1[key]))  

 

以上为定义传统字典类型时的一个简单排序过程。 如果我们定义一个有序字典时,将不用再如此麻烦, 字典顺序将按照录入顺序进行排序且不会改变。

# 定义有序字典  

dic2 = OrderedDict()  

dic2['a'] = '123'  

dic2['b'] = 'jjj'  

dic2['c'] = 'abc'  

dic2['d'] = '999'  

for k, v in dic2.iteritems():  

    print('有序字典:%s:%s' %(k,v)) 

 

5.nametuple

namedtuple是一个函数,它用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。

标准的tuple类型使用数字索引来访问元素

bob = ('Bob', 30, 'male')  

print('Representation:', bob)  

  

jane = ('Jane', 29, 'female')  

print('\nField by index:', jane[0])  

  

print('\nFields by index:')  

for p in [bob, jane]:  

    print('%s is a %d year old %s' % p) 

这种对于标准的元组访问,我们需要知道元素对应下标索引值,但当元组的元素很多时,我们可能无法知道每个元素的具体索引值,这个时候就是可命名元组登场的时候了。

nametuple 的创建是由自己的类工厂nametuple()进行创建,而不是由标准的元组来进行实例化,通过nametuple()创建类的参数包括类名称和一个包含元素名称的字符串

from collections import namedtuple  

#创建一个nametuplede 类,类名称为Person,并赋给变量P  

P = namedtuple('Person', 'name,age,gender')  

print('Type of Person:', type(P))  # Type of Person: <class 'type'>  

  

#通过Person类实例化一个对象bob  

bob = P(name='Bob', age=30, gender='male')  

print('\nRepresentation:', bob)  # Representation: Person(name='Bob', age=30, gender='male')  

  

#通过Person类实例化一个对象jane  

jane = P(name='Jane', age=29, gender='female')  

print('\nField by name:', jane.name)  # Field by name: Jane  

  

print('\nFields by index:')  

for p in [bob, jane]:  

    print('%s is a %d year old %s' % p)  

# Fields by index:  

# Bob is a 30 year old male  

# Jane is a 29 year old female  

通过上面的实例可以看出,我们通过nametuple()创建了一个Person的类,并复制给P变量,Person的类成员包括name,age,gender,并且顺序已经定了,在实例化zhangsan这个对象的时候,对张三的属性进行了定义。这样我们在访问zhangsan这个元组的时候就可以通过张三的属性来复制(zhangsan.name、zhangsan.age等)。这样就算这个元组有1000个元素我们都能通过元素的名称来访问而不用考虑元素的下标索引值。

非法的参数值

使用nametuple()来创建类的时候,传递的成员属性参数名称不能非法(不能为系统参数名称),且参数名称不能重复,否则会报值错误

#参数字段的名称非法,包含系统名称class  

try:  

    p = namedtuple('Person','age,name,class,gender')  

    print(p._fields)  

except ValueError as err:  

    print(err)  

  

#Type names and field names cannot be a keyword: 'class'    

#类成员字段参数名称重复 age  

try:  

    p1 = namedtuple('Person','age,gender,name,age')  

    print(p1._fields)  

except ValueError as err:  

    print(err)  

#Encountered duplicate field name: 'age'  

但是也有时候我们是无法控制的,如果参数的名称来自外部,比如是通过读取数据库中的内容来传递的参数,此时我们无法手工的修改参数名称,那该如何是好呢! 别担心,只需要增加一个属性就OK了,它就是rename

#参数字段的名称非法,包含系统名称class  

try:  

    p = namedtuple('Person','age,name,class,gender',rename=True)  

    print(p._fields)  

except ValueError as err:  

    print(err)  

  

# ('age', 'name', '_2', 'gender')  

# 类成员字段参数名称重复 age  

try:  

    p1 = namedtuple('Person','age,gender,name,age',rename=True)  

    print(p1._fields)  

except ValueError as err:  

    print(err)  

# ('age', 'gender', 'name', '_3')  

从以上的实例我们看出,当有参数错误的时候,系统自动将错误的参数通过增加 "下划线+参数索引" 的方式自动将参数名称替换了。

 

2.bisect实现有序序列的插入和查找,有序序列即为元素值已排序好的列表

https://docs.python.org/zh-cn/3/library/bisect.html?highlight=bisect#module-bisect

bisect是python内置模块,用于有序序列的插入和查找。

(1)查找

import bisect

a = [1,4,6,8,12,15,20]

position = bisect.bisect(a,13)

print(position)

 

(2)插入

a.insert(position,13)

print(a)

[1, 4, 6, 8, 12, 13, 15, 20]

 

(3)常用函数

# bisect.bisect(a, x, lo=0, hi=None)

# bisect.bisect_left(a, x, lo=0, hi=None)

# bisect.bisect_right(a, x, lo=0, hi=None)

# bisect.insort(a, x, lo=0, hi=None)

# bisect.insort_left(a, x, lo=0, hi=None)

# bisect.insort_right(a, x, lo=0, hi=None)

# bisect(a, x, lo=0, hi=None) = bisect_right(a, x, lo=0, hi=None)

# insort(a, x, lo=0, hi=None) = insort_right(a, x, lo=0, hi=None)

 

3.python queue队列

queue 模块实现多生产者,多消费者队列

https://docs.python.org/zh-cn/3.6/library/queue.html

https://blog.csdn.net/weixin_43533825/article/details/89155648

 

5.random随机模块

1.随机整数

random.randint(a, b)生成指定范围内的整数,即 a <= n <= b

import random

random.randint(0,99)

 

2.随机选取0到100间的偶数

random.randrange(0, 101, 2)

 

3.随机浮点数

random.random() 

#0.85415370477785668

random.uniform(1, 10)

#5.4221167969800881

 

4.随机字符

random.choice('abcdefg&#%^*f')

 

5.多个字符中选取特定数量的字符

random.sample('abcdefghij',3) 

#['a', 'd', 'b']

 

6.多个字符中选取特定数量的字符组成新字符串

import random

import string

string.join(random.sample(['a','b','c','d','e','f','g','h','i','j'], 3)).replace(" ","")

#'fih'

 

7.随机选取字符串

random.choice ( ['apple', 'pear', 'peach', 'orange', 'lemon'] )

#'lemon'

 

8.洗牌

import random

items = [1, 2, 3, 4, 5, 6]

random.shuffle(items)

items

#[3, 2, 5, 6, 4, 1]

 

    原文作者:开码牛
    原文地址: https://blog.csdn.net/helunqu2017/article/details/112975039
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。