这其实是数的第五章内容
此时的我早已经通读此书, 总的来说没啥子收获,我想了解一些可以出去装B的东西, 很不巧, 这会本书,,
第五章主要讲的是py内置的数据结构
字典结构
1 OrderedDict 能记住字典顺序的字典
其实,现在也没啥子用处了。从py3.6开始,字典就是能记住顺序的,这里说的是插入顺序。
import collections
d = collections.OrderedDict(one=1, two=2, three=3)
print(d) # OrderedDict([('one', 1), ('two', 2), ('three', 3)])
d['four'] = 4
print(d) # OrderedDict([('one', 1), ('two', 2), ('three', 3), ('four', 4)])
print(d.keys()) # odict_keys(['one', 'two', 'three', 'four'])
2 defaultdict 为缺失的键返回默认值
这个还是有些用处的。
default_factory 接收一个工厂函数作为参数, 例如int str list set等.
from collections import defaultdict
dd = defaultdict(list)
dd['dogs'].append("Rufus")
dd['dogs'].append("Kathrin")
dd['dogs'].append("Mr Sniffles")
print(dd['dogs'])
# ['Rufus', 'Kathrin', 'Mr Sniffles']
from collections import defaultdict
dd = defaultdict(set)
dd['dogs'].add("Rufus")
dd['dogs'].add("Kathrin")
dd['dogs'].add("Mr Sniffles")
print(dd['dogs'])
# {'Mr Sniffles', 'Kathrin', 'Rufus'}
3 ChainMap 搜索多个字典
将多个字典分组到一个映射中,在查找时逐个搜索底层映射,直到找到一个符合条件的键。对ChainMap进行插入、更新和删除操作,只会作用于其中第一个字典。
感觉有点东西, 虽然不知道有啥用
from collections import ChainMap
dict1 = {'one': '1', 'two': 2}
dict2 = {'three': 3, 'four': 4}
chain = ChainMap(dict1, dict2)
print(chain) # ChainMap({'one': '1', 'two': 2}, {'three': 3, 'four': 4})
print(chain['four']) # 4
chain['six'] = "6"
print(chain) # ChainMap({'one': '1', 'two': 2, 'six': '6'}, {'three': 3, 'four': 4})
# 对ChainMap 进行插入、更新和删除操作,只会作用于其中的一个字典。
4 collection.Counter 多重集合
就是两个字典键相同, 合并值, 如果值是数字类型就直接相加,字符串类型就直接拼接。
from collections import Counter
inventory = Counter()
loot = {'sword': 1, 'bread': 3, 'aki': 'de'}
inventory.update(loot)
print(inventory) # Counter({'sword': 1, 'bread': 3, 'aki': 'de'})
more_loot = {'sword': 1, 'apple': 1, 'aki': 'sky'}
inventory.update(more_loot)
print(inventory) # Counter({'sword': 2, 'bread': 3, 'aki': 'skyde', 'apple': 1})
元组类型
元组没啥说的,主要是下面这种写法,第一次见到过。
arr = 'one', 'twp', 'th'
print(arr) # ('one', 'twp', 'th')
1 nametuple
没啥好说的,nametuple 和tuple 占用的空间是一样的, 是不可变的
from collections import namedtuple
from sys import getsizeof
p1 = namedtuple("Point", 'x y z')(1, 2, 3) # 注意'x y z' 相当于【‘x', 'y', 'z'】 内部通过空格把字符串转成列表
p2 = (1, 2, 3)
print(getsizeof(p1)) # 72
print(getsizeof(p2)) # 72
from collections import namedtuple
Car = namedtuple('Car', 'color, mileage automatic')
car1 = Car('red', 123344, True)
print(car1) # Car(color='red', mileage=123344, automatic=True)
print(car1.mileage)
2 typing.NameTuple 改进版的nametuple
它是3.6才加进来的, 和namedtuple 极为类似, 不过它是类的写法
from typing import NamedTuple
class Car(NamedTuple):
color: str
mileage: float
automatic: bool
car1 = Car('red', 1234, True)
print(car1) # Car(color='red', mileage=1234, automatic=True
print(car1.mileage) # 1234
# car1.mileage = 555555 会报错, 因为是不可变对象
3 types.SimpleNamespace 花哨的属性访问
SimpleNamespace实例将其中的所有键都公开为类属性,因此访问属性时可以使用obj.key这样的点式语法。
from types import SimpleNamespace
car1 = SimpleNamespace(color='red', mileage='1234', automatic=True)
print(car1) # namespace(automatic=True, color='red', mileage='1234')
print(car1.mileage) # 1234
# 属性式可变的
car1.mileage = '666'
print(car1.mileage)
数组类型
列表我就不多BB了
1 array.array 基本类型数组
Python的arr模块占用的空间较小,用于存贮C语言风格的基本数据类型。使用array.array 类创建的数组是可变的,行为于列表相似。但有一个重要的区别,这种数组是单一类型的“数组数组”。就是只能存一种统一的类型,这个类型还要提前通过参数设定。最大的优点就是节省空间。
Type code C Type Minimum size in bytes
'b' signed integer 1
'B' unsigned integer 1
'u' Unicode character 2 (see note)
'h' signed integer 2
'H' unsigned integer 2
'i' signed integer 2
'I' unsigned integer 2
'l' signed integer 4
'L' unsigned integer 4
'q' signed integer 8 (see note)
'Q' unsigned integer 8 (see note)
'f' floating point 4
'd' floating point 8
import array
arr = array.array('f', (1.0, 2.5, 2.0, 2.5))
print(arr[1])
2 bytes 含有单字节的不可变数组
bytes对象是单字节的不可变序列,单字节为0-255范围内的整数,从概念上讲,bytes与str对象类似,可认为是不可变的字节数组。bytes是不可变对象。
>>> arr = bytes((0, 1, 2, 3))
>>> arr
b'\x00\x01\x02\x03'
>>> arr[1]
1
>>> bytes((0, 300)) # 范围是0-255
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: bytes must be in range(0, 256)
>>> arr[1] = 55 # 不可变
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'bytes' object does not support item assignment
3 bytearray 含有单字节的可变数组
bytearray类型是可变整数序列,包含0-255,bytearray 和bytes极为类似, 不过它是可变的。
>>> arr = bytearray((0, 1, 2, 3))
>>> arr[1]
1
>>> arr
bytearray(b'\x00\x01\x02\x03')
>>> arr[1] = 23 # bytearray是可变的
>>> arr[1]
23
>>> del arr[1] # 可以删除指定位置的元素
>>> arr
bytearray(b'\x00\x02\x03')
集合类型
set类型式可变的。set没啥好说的。
1 frozenset 不可变集合
可以用作字典的键, 也可以放在另一个集合中。普通的可变集合做不到这一点。
vowels = frozenset({'a', 'e', 'i', 'o', 'u'})
vowels.add('p')
# 会报错, 因为fronzenset是不可变集合
下面就有些nB了
d = {frozenset({1, 2, 3}): 'hello'}
print(d[frozenset({1, 2, 3})])
栈类型
1 列表
用列表的append, pop方法, 把列表维护成栈, 效率还是很高的, 因为尾加尾删时间复杂度都是O(1)
2 collections.deque
双端队列, 内部是双向链表, 就不多BB了。
3 queue.LifoQueue 不知道有啥用
这个就是个官方的队列, 名字也很通俗, 后进先出队列。
from queue import LifoQueue
s = LifoQueue()
s.put('eat')
s.put('sleep')
s.put('code')
print(s) # <queue.LifoQueue object at 0x0000025F88981550>
print(s.get()) # code
print(s.get()) # sleep
print(s.get()) # eat
# print(s.get()) # 多get一个也不报错 因为阻塞了
# print(s.get_nowait()) # 不阻塞,不没有了, 立即终止程序
队列结构
1 列表和双端队列做成队列, 不多说了, 不过列表效率太TM低了。
2 queue.Queue 跟上面的LifoQueue 是一个样子
from queue import Queue
s = Queue()
s.put('eat')
s.put('sleep')
s.put('code')
print(s) # <queue.LifoQueue object at 0x0000025F88981550>
print(s.get()) # code
print(s.get()) # sleep
print(s.get()) # eat
# print(s.get()) # 多get一个也不报错 因为阻塞了
# print(s.get_nowait()) # 不阻塞,不没有了, 立即终止程序
3 multiprocessing.Queue
共享作业队列,允许多个并发worker并行处理队列中元素,能绕过GIL的性能的限制
from multiprocessing import Queue
s = Queue()
s.put('eat')
s.put('sleep')
s.put('code')
print(s) # <queue.LifoQueue object at 0x0000025F88981550>
print(s.get()) # code
print(s.get()) # sleep
print(s.get()) # eat
# print(s.get()) # 多get一个也不报错 因为阻塞了
4 queue.PriorityQueue 优先队列
内部是二叉树的小根堆实现的, 所以前面的数越小, 优先级越高。注意里面是元组
from queue import PriorityQueue
q = PriorityQueue()
q.put((2, 'code')) # 注意内部是元组
q.put((1, 'eat'))
q.put((3, 'sleep'))
print(q.get_nowait()) # (1, 'eat')
print(q.get()) # (2, 'code')
也可以至指定元素,元素只能是数字或字符串,类型还必须统一
from queue import PriorityQueue
q = PriorityQueue()
q.put("fds")
q.put("as")
q.put("sd")
print(q.get_nowait()) # as
print(q.get()) # fds