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
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)
编程实践中我们经常需要创建一些小的数据结构用来整合一组相关联的数据,简单的比如地理坐标的经纬度,颜色的RGB值或者矩形框的左上和右下坐标,复杂的比如构造一个窗口的一组参数。
实践中,我们通常有3中实现方法:
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是用来对元素进行计数的,它也是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})
除了基本的计数功能,它还支持一些常用的相关功能。比如:
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图像处理之图像拼接