4种非常实用的python内置数据结构


Posted in Python onApril 28, 2021

array

Python不仅仅可以使用内置的list实现数组,还支持像C语言那样的指定类型的原生数组array。
很显然,因为list可以存储各种类型的对象,而array只存储一个指定的原生类型,所以当数据量较大时,原生array在内存占用方面要比list小。
而且array不像C语言里那样在定义时就限制了大小,它支持list所支持的各种常用函数。相比之下Python的array更像是C++的vector。

from array import array
l = list(range(100))
a = array.fromlist(l)

print(l.__sizeof__(), a.__sizeof__())

目前array有两个限制。首先,它只支持整数、小数、unicode字符,而不能像C++的vector那样支持多种数据类型。另外目前指定类型比较麻烦,我们需要使用类型对应的字母缩写来指定,而不能使用简单的诸如int,float的方式。

a = array('i')
a.append(1)
a.append(4)
Type code  C Type Python Type Minimum size in bytes
'b' signed char int 1
'B'  unsigned char int 1
'u' wchar_t  Unicode character 2
'h'  signed short int 2
'H'  unsigned short int 2
'i' signed int int 2
'I'  unsigned int int 2
'l' signed long int 4
'L'  unsigned long int 4

更详细的信息可以参考:https://docs.python.org/3.8/library/array.html

defaultdict

C++的map对于新的key会自动使用value type的默认构造函数构造一个值,而Python默认的dict对于不存在的key的访问会抛出异常(赋值除外)。这是因为Python不知道value的类型,所以没办法为我们默认构造。
defaultdict要求我们在构造时指定一个类型,然后会自动根据需要初始化value。这样我们就可以使用简单的代码来实现很多功能。

下面的代码,我对比了使用defaultdict和original dict实现将学生按照姓的首字母分组的功能,以及分类计数的功能。

import collections
students = ['Zhang San', 'Li Si', 'Zhou liu', 'Chen qi', 'Cheng ba']
# using defaultdict
dd = collections.defaultdict(list)
for s in students:
	key = s[0]
	dd[key].append(s)
print(dd)
# using original dict (method 1)
od = {}
for s in students:
	key = s[0]
	if key not in do:
		od[key] = []
	od[key].append(s)
print(od)

scores = ['A', 'B', 'C', 'A', 'A', 'B', 'C', 'B', 'A', 'A']
# using defaultdict
dd = collections.defaultdict(int)
for s in scores :
	dd[s] += 1
print(dd)
# using original dict (method 2)
od = collections.defaultdict(int)
for s in scores :
	if s not in do:
		do[s] = 1
	else:
		do[s] += 1
print(od)

Named Tuple

编程实践中我们经常需要创建一些小的数据结构用来整合一组相关联的数据,简单的比如地理坐标的经纬度,颜色的RGB值或者矩形框的左上和右下坐标,复杂的比如构造一个窗口的一组参数。
实践中,我们通常有3中实现方法:

  • 对每一个这样的数据结构创建一个class。优点是可以直接使用名字访问数据成员,而且支持复杂的访问逻辑和数据操作。缺点是需要编写对应的类和必须的函数,管理文件和引用关系。
  • 使用tuple。优点是编写简单,内存使用效率高。缺点是只能使用下标访问,可读性差,容易出错。
  • 使用dict,用str来作为对于属性的名字。优点是编写相对简单,而且保留了变量的名字。缺点是需要使用字符串表示名字较为麻烦,而且每一个结构都要保存作为名字的字符串,浪费空间。

collections的nametuple可以为我们直接构造一个具有名字的简单类型,方便快捷地实现类似手写了一个class的效果。
需要注意的是collections.nametuple是一个factory function,它用来帮我们创建一个类型,而不是这个类型的具体对象。创建类型时,我们可以指定各个属性的名字,之后就可以使用.来访问了,而且它同时还支持使用下标访问。同时Named Tuple还支持_asdict函数用来将内部的数值转换成一个dict。

# class
class Rect:
	def __init__(self, x1, y1, x2, y2):
		self.x1 = x1
		self.y1 = y1
		self.x2 = x2
		self.y2 = y2
		
def area_class(r):
	w = r.x2 - r.x1
	h = r.y2 - r.y1
	return w*h

r1 = Rect(1,3,5,5)
# <__main__.Rect object at 0x7fde252a87f0>
# to show its content, we need to implement __repr__(self) or __str__(self)
print(area_class(r1))

# tuple
def area_tuple(r):
	w = r[2]-r[0]
	h = r[3]-r[1]
	return w*h

r2 = (1,3,5,5)
print(r2)
# (1, 3, 5, 5)
print(area_tuple(r2))

# dict
def area_dict(r):
	w = r["x2"] - r["x1"]
	h = r["y2"] - r["y1"]
	return w*h

r3 = {"x1":1, "y1":3, "x2":5, "y2":5}
print(r3)
# {'x1': 1, 'y1': 3, 'x2': 5, 'y2': 5}
print(area_tuple(r3))

# named tuple
import collections
Rectangle = collections.namedtuple("Rectangle", ["x1", "y1", "x2", "y2"])

def area_namedtuple(r):
	w = r.x2 - r.x1
	y = r.y2 - r.y1
	return w*h

r4 = Rectangle(1,3,5,5)
print(r4)
# Rectangle(x1=1, y1=3, x2=5, y2=5)
x1,y2,x2,y2 = r4
print(x1,y2,x2,y2)
# 1 3 5 5
print(area_namedtuple(r4))
print(area_class(r4)) # work with "." grammar
print(area_tuple(r4)) # work with index
print(area_dict(r4._asdict())) # work with dict

Counter

顾名思义,Counter是用来对元素进行计数的,它也是collections这个包里的。根据Python的官方文档,它是dict类型的一个子类。
在构造的时候输入一个iterable的类型,比如list,range或是一个mapping的类型,比如dict,defaultdict。然后Counter就会对其中的元素进行计数。
比较特殊的是,Counter对负数没有做特殊处理,就是说在特殊操作下允许出现测试为负,后面我们会有例子。

c = Counter()                           # a new, empty counter
c = Counter('gallahad')                 # a new counter from an iterable
print(c)
# Counter({'a': 3, 'l': 2, 'g': 1, 'h': 1, 'd': 1})
c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
print(c)
# Counter({'red': 4, 'blue': 2})
c = Counter(cats=4, dogs=8)             # a new counter from keyword args
print(c)
# Counter({'dogs': 8, 'cats': 4})

除了基本的计数功能,它还支持一些常用的相关功能。比如:

  • 按照频率排序(most_common([n]))。其中n是可选输入,表示返回前n个最频繁的元素和他们的频率。默认情况下返回所有的元素。
  • 按照频率输出元素本身(elements())。它会返回元素本身,但是元素的顺序不是原来的,相同的元素会连续输出。不同元素之间,按照他们的出现顺序输出,这一点是OrderedDict以及3.7之后的dict所提供的特性。
  • 两个Counter相减(substract(c))。它可以从第一个counter上减去第二个counter中对应元素出现的次数。对于只出现在第二个coutner中元素,默认其在第一个counter中出现0次。
c = Counter(a=4, b=2, c=0, d=-2)
sorted(c.elements())
# ['a', 'a', 'a', 'a', 'b', 'b']
Counter('abracadabra').most_common(3)
# [('a', 5), ('b', 2), ('r', 2)]

c1 = Counter(a=4, b=2, d=-2)
c2 = Counter(a=1, b=2, c=3, d=4)
c1.subtract(c2)
c1
# Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

更多的参考信息大家可以参考官方文档:

https://docs.python.org/3/library/collections.html

以上就是4种非常实用的python内置数据结构的详细内容,更多关于python内置数据结构的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python获取网页上图片下载地址的方法
Mar 11 Python
Python字典,函数,全局变量代码解析
Dec 18 Python
Python实现改变与矩形橡胶的线条的颜色代码示例
Jan 05 Python
python更改已存在excel文件的方法
May 03 Python
Python实现获取nginx服务器ip及流量统计信息功能示例
May 18 Python
使用python画个小猪佩奇的示例代码
Jun 06 Python
使用EduBlock轻松学习Python编程
Oct 08 Python
对python3中, print横向输出的方法详解
Jan 28 Python
Python面向对象实现一个对象调用另一个对象操作示例
Apr 08 Python
Python集中化管理平台Ansible介绍与YAML简介
Jun 12 Python
Pycharm新建模板默认添加个人信息的实例
Jul 15 Python
pycharm配置QtDesigner的超详细方法
Jan 25 Python
Python基础详解之描述符
Apr 28 #Python
详解Python 3.10 中的新功能和变化
Apr 28 #Python
Python基础之数据结构详解
Apr 28 #Python
Python基础详解之邮件处理
python实现黄金分割法的示例代码
Apr 28 #Python
Python 流媒体播放器的实现(基于VLC)
tensorflow+k-means聚类简单实现猫狗图像分类的方法
You might like
C# Assembly类访问程序集信息
2009/06/13 PHP
PHP中10个不常见却非常有用的函数
2010/03/21 PHP
ThinkPHP3.1新特性之多层MVC的支持
2014/06/19 PHP
PHP生成不重复标识符的方法
2014/11/21 PHP
Laravel5.7 数据库操作迁移的实现方法
2019/04/12 PHP
有关js的变量作用域和this指针的讨论
2010/12/16 Javascript
JavaScript动态调整TextArea高度的代码
2010/12/28 Javascript
仅IE9/10同时支持script元素的onload和onreadystatechange事件分析
2011/04/27 Javascript
计算世界完全对称日的js代码,粗糙版
2011/11/04 Javascript
使用jquery实现IE下按backspace相当于返回操作
2014/03/18 Javascript
推荐5 个常用的JavaScript调试技巧
2015/01/08 Javascript
JS实现自适应高度表单文本框的方法
2015/02/25 Javascript
JavaScript中判断两个字符串是否相等的方法
2015/07/07 Javascript
JS控制表单提交的方法
2015/07/09 Javascript
AngualrJS中每次$http请求时的一个遮罩层Directive
2016/01/26 Javascript
jquery ajax后台返回list,前台用jquery遍历list的实现
2016/10/30 Javascript
详解vue事件对象、冒泡、阻止默认行为
2017/03/20 Javascript
浅谈react.js 之 批量添加与删除功能
2017/04/17 Javascript
微信小程序 本地图片按照屏幕尺寸处理
2017/08/04 Javascript
vue和react等项目中更简单的实现展开收起更多等效果示例
2018/02/22 Javascript
webpack4.0 入门实践教程
2018/10/08 Javascript
浅谈layer弹出层按钮颜色修改方法
2019/09/11 Javascript
[03:22]DAC最前线(第二期)—DOTA2亚洲邀请赛主赛场周边及线路探访
2015/01/24 DOTA
下载糗事百科的内容_python版
2008/12/07 Python
python创建只读属性对象的方法(ReadOnlyObject)
2013/02/10 Python
python实现的用于搜索文件并进行内容替换的类实例
2015/06/28 Python
Python实现的查询mysql数据库并通过邮件发送信息功能
2018/05/17 Python
pycharm debug功能实现跳到循环末尾的方法
2018/11/29 Python
Python面向对象实现一个对象调用另一个对象操作示例
2019/04/08 Python
OpenCV中VideoCapture类的使用详解
2020/02/14 Python
毕业生自荐书
2013/12/18 职场文书
春节联欢晚会主持词范文
2014/03/24 职场文书
幼儿园清明节活动总结
2014/07/04 职场文书
幼儿园六一亲子活动方案
2014/08/26 职场文书
CSS Transition通过改变Height实现展开收起元素
2021/08/07 HTML / CSS
「SHOW BY ROCK!!」“雫シークレットマインド”组合单曲MV公开
2022/03/21 日漫