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的绘图工具matplotlib使用实例
Jul 03 Python
Python库urllib与urllib2主要区别分析
Jul 13 Python
python之wxPython应用实例
Sep 28 Python
python使用range函数计算一组数和的方法
May 07 Python
网站渗透常用Python小脚本查询同ip网站
May 08 Python
Python实现Linux中的du命令
Jun 12 Python
python爬取各类文档方法归类汇总
Mar 22 Python
Django中的文件的上传的几种方式
Jul 23 Python
APIStar:一个专为Python3设计的API框架
Sep 26 Python
python输出带颜色字体实例方法
Sep 01 Python
python3 使用ssh隧道连接mysql的操作
Dec 05 Python
详解Pycharm第三方库的安装及使用方法
Dec 29 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/01/01 PHP
php中将字符串转为HTML的实体引用的一个类
2013/02/03 PHP
php多层数组与对象的转换实例代码
2013/08/05 PHP
php抓取并保存网站图片的实现代码
2015/10/28 PHP
PHP利用超级全局变量$_POST来接收表单数据的实例
2016/11/05 PHP
PHP+Session防止表单重复提交的解决方法
2018/04/09 PHP
thinkPHP5.1框架路由::get、post请求简单用法示例
2019/05/06 PHP
php fread函数使用方法总结
2019/05/28 PHP
TP5框架使用QueryList采集框架爬小说操作示例
2020/03/26 PHP
Kibo 用于处理键盘事件的Javascript工具库
2011/10/28 Javascript
原生js写的放大镜效果
2012/08/22 Javascript
javascript实现checkbox全选的代码
2015/04/30 Javascript
跟我学习javascript的arguments对象
2015/11/16 Javascript
微信小程序 高德地图SDK详解及简单实例(源码下载)
2017/01/11 Javascript
初探nodeJS
2017/01/24 NodeJs
JavaScript中.min.js和.js文件的区别讲解
2019/02/13 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
2019/12/02 Javascript
基于JavaScript实现猜数字游戏代码实例
2020/07/30 Javascript
vue项目实现多语言切换的思路
2020/09/17 Javascript
[01:09:20]NB vs NAVI Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
[01:48:04]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Elephant BO3 第一场 2月7日
2021/03/11 DOTA
[08:54]DOTA2-DPC中国联赛 正赛 Aster vs LBZS 选手采访
2021/03/11 DOTA
Python抓取百度查询结果的方法
2015/07/08 Python
python控制台中实现进度条功能
2015/11/10 Python
使用XML库的方式,实现RPC通信的方法(推荐)
2017/06/14 Python
Python学习笔记之抓取某只基金历史净值数据实战案例
2019/06/03 Python
使用python 的matplotlib 画轨道实例
2020/01/19 Python
计算Python Numpy向量之间的欧氏距离实例
2020/05/22 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
美津浓美国官网:Mizuno美国
2018/08/07 全球购物
AJAX的优缺点都有什么
2015/08/18 面试题
经理秘书找工作求职信
2013/12/19 职场文书
立志成才演讲稿
2014/09/04 职场文书
华山导游词
2015/02/03 职场文书
2019个人年度目标制定攻略!
2019/07/12 职场文书
职业规划从高考志愿专业选择开始
2019/08/08 职场文书