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使用nntp读取新闻组内容的方法
May 08 Python
详解Python核心编程中的浅拷贝与深拷贝
Jan 07 Python
pandas获取groupby分组里最大值所在的行方法
Apr 20 Python
运用Python的webbrowser实现定时打开特定网页
Feb 21 Python
使用matplotlib中scatter方法画散点图
Mar 19 Python
Python3获取电脑IP、主机名、Mac地址的方法示例
Apr 11 Python
解决python super()调用多重继承函数的问题
Jun 26 Python
浅谈Python2之汉字编码为unicode的问题(即类似\xc3\xa4)
Aug 12 Python
用sqlalchemy构建Django连接池的实例
Aug 29 Python
Tensorflow实现在训练好的模型上进行测试
Jan 20 Python
Pycharm中切换pytorch的环境和配置的教程详解
Mar 13 Python
pytorch随机采样操作SubsetRandomSampler()
Jul 07 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 引用文件技巧
2010/03/02 PHP
PHP 二维array转换json的实例讲解
2018/08/21 PHP
Laravel使用scout集成elasticsearch做全文搜索的实现方法
2018/11/30 PHP
PHP使用SOAP调用API操作示例
2018/12/25 PHP
图片完美缩放
2006/09/07 Javascript
jQuery 入门讲解1
2009/04/15 Javascript
javascrip客户端验证文件大小及文件类型并重置上传
2011/01/12 Javascript
使用jQuery UI的tooltip函数修饰title属性的气泡悬浮框
2013/06/24 Javascript
jQuery操作JSON的CRUD用法实例
2015/02/25 Javascript
jQuery简单实现QQ空间点赞已经取消点赞
2015/04/02 Javascript
jquery if条件语句的写法
2016/05/19 Javascript
JQuery EasyUI Layout 在from布局自适应窗口大小的实现方法
2016/05/28 Javascript
jQuery滚动新闻实现代码
2016/06/26 Javascript
理解AngularJs篇:30分钟快速掌握AngularJs
2016/12/23 Javascript
清空元素html(&quot;&quot;) innerHTML=&quot;&quot; 与 empty()的区别和应用(推荐)
2017/08/14 Javascript
Vue.js项目模板搭建图文教程
2017/09/20 Javascript
使用js获取伪元素的content实例
2017/10/24 Javascript
React Router v4 入坑指南(小结)
2018/04/08 Javascript
vue-router命名路由和编程式路由传参讲解
2019/01/19 Javascript
python爬虫之线程池和进程池功能与用法详解
2018/08/02 Python
基于numpy中数组元素的切片复制方法
2018/11/15 Python
Python通过for循环理解迭代器和生成器实例详解
2019/02/16 Python
Python Django Vue 项目创建过程详解
2019/07/29 Python
pycharm 更改创建文件默认路径的操作
2020/02/15 Python
Python导入数值型Excel数据并生成矩阵操作
2020/06/09 Python
浅谈amaze-ui中datepicker和datetimepicker注意的几点
2020/08/21 HTML / CSS
加拿大消费电子和手机购物网站:The Source
2017/01/28 全球购物
捷克鲜花配送:Florea.cz
2018/10/29 全球购物
梅花魂教学反思
2014/04/25 职场文书
统计员岗位职责
2015/02/11 职场文书
校长师德表现自我评价
2015/03/04 职场文书
罚款通知怎么写
2015/04/22 职场文书
小学教研工作总结2015
2015/05/13 职场文书
vue css 相对路径导入问题级踩坑记录
2022/06/05 Vue.js
Win11自动黑屏怎么办 Win11自动黑屏设置教程
2022/07/15 数码科技
详解MySQL的内连接和外连接
2023/05/08 MySQL