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实现倒计时的示例
Feb 14 Python
Python生成器(Generator)详解
Apr 13 Python
python开发之函数定义实例分析
Nov 12 Python
Python中异常重试的解决方案详解
May 05 Python
Python输出由1,2,3,4组成的互不相同且无重复的三位数
Feb 01 Python
Python matplotlib 画图窗口显示到gui或者控制台的实例
May 24 Python
pandas 数据实现行间计算的方法
Jun 08 Python
解决Pycharm中恢复被exclude的项目问题(pycharm source root)
Feb 14 Python
TensorFlow打印输出tensor的值
Apr 19 Python
python 识别登录验证码图片功能的实现代码(完整代码)
Jul 03 Python
Python如何绘制日历图和热力图
Aug 07 Python
一篇文章带你了解Python和Java的正则表达式对比
Sep 15 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
php addslashes 函数详细分析说明
2009/06/23 PHP
基于flush()不能按顺序输出时的解决办法
2013/06/29 PHP
PHP修改session_id示例代码
2014/01/08 PHP
PHP实现的mysql主从数据库状态检测功能示例
2017/07/20 PHP
CSS心形加载的动画源码的实现
2021/03/09 HTML / CSS
popdiv
2006/07/14 Javascript
jquery获取table中的某行全部td的内容方法
2013/03/08 Javascript
js检测网络是否具体连接功能的代码
2014/05/23 Javascript
jQuery/CSS3图片特效插件整理推荐
2014/12/07 Javascript
jquery实现很酷的网页顶部图标下拉菜单效果
2015/08/22 Javascript
最原始的jQuery注册验证方式
2016/10/11 Javascript
javascript函数的四种调用模式
2017/01/08 Javascript
浅谈js停止事件冒泡 阻止浏览器的默认行为(阻止超连接 #)
2017/02/08 Javascript
javaScript+turn.js实现图书翻页效果实例代码
2017/02/16 Javascript
从零开始学习Node.js系列教程三:图片上传和显示方法示例
2017/04/13 Javascript
bootstrap paginator分页前后台用法示例
2017/06/17 Javascript
JavaScript定义函数的三种实现方法
2017/09/23 Javascript
详解Vue组件实现tips的总结
2017/11/01 Javascript
python 实现堆排序算法代码
2012/06/05 Python
详解python中的文件与目录操作
2017/07/11 Python
Python基于list的append和pop方法实现堆栈与队列功能示例
2017/07/24 Python
PYTHON基础-时间日期处理小结
2018/05/05 Python
Python正则匹配判断手机号是否合法的方法
2020/12/09 Python
简单了解Python3 bytes和str类型的区别和联系
2019/12/19 Python
python如何绘制疫情图
2020/09/16 Python
使用Python解析Chrome浏览器书签的示例
2020/11/13 Python
利用Python批量识别电子账单数据的方法
2021/02/08 Python
威尔逊皮革:Wilsons Leather
2018/12/07 全球购物
日本航空官方网站:JAL
2019/06/19 全球购物
新驾驶员个人自我评价
2014/01/03 职场文书
高三地理教学反思
2014/01/11 职场文书
向领导表决心的话
2014/03/11 职场文书
史上最牛的辞职信
2015/02/28 职场文书
党员进社区活动总结
2015/05/07 职场文书
创业计划书之电动车企业
2019/10/11 职场文书
总结三种用 Python 作为小程序后端的方式
2022/05/02 Python