企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] ## 1. weakref 1. 和许多其它的高级语言一样,Python使用了**垃圾回收器来自动销毁那些不再使用的对象**。每个对象都有一个引用计数,当这个引用计数为0时Python能够安全地销毁这个对象。 2. 使用weakref模块,你可以创建到对象的弱引用,Python在对象的引用计数为0或只存在对象的弱引用时将回收这个对象。 ### 1.1 WeakValueDictionary, WeakKeyDictionary 弱引用mapping对象, 以WeakValueDictionary来说, 当键对应的值除了mapping本身引用之外没有其他引用的情况下,会回收掉这个值,相应的这个键值对就不存在了 ~~~ import weakref class TestObject(object): value = 'hello weakref' d = weakref.WeakValueDictionary() d[1] = TestObject() ~~~ 除了 d[1] 引用这个对象之外没有其他引用,立即被垃圾回收器收回了 ~~~ >> d[1] KeyError Traceback (most recent call last) <ipython-input-19-6ee4d8336f71> in <module>() ----> 1 d[1] C:\Python34\lib\weakref.py in __getitem__(self, key) 123 124 def __getitem__(self, key): --> 125 o = self.data[key]() 126 if o is None: 127 raise KeyError(key) KeyError: 1 ~~~ ~~~ >> d <WeakValueDictionary at 76992912> ~~~ ~~~ >> obj = TestObject() >> d[1] = obj ~~~ 由于obj还被main模块所引用,因此可以访问到这个键值对 ~~~ >> d[1] <__main__.TestObject at 0x944650> ~~~ 注: 对WeakValueDictionary对象使用valuerefs()方法进行遍历时,并不能保证这个字典不会改变,可能存在遍历过程中值被垃圾回收器收回的风险。 对于WeakKeyDictionary来说它类似于WeakValueDictionary, 只不过这时候弱引用作用于键上面。 ## 2.struct 数据格式转换 > Python是一门非常简洁的语言,对于数据类型的表示,不像其他语言预定义了许多类型(如:在C#中,光整型就定义了8种),它只定义了六种基本类型:字符串,整数,浮点数,元组,列表,字典。通过这六种数据类型,我们可以完成大部分工作。但当Python需要通过网络与其他的平台进行交互的时候,必须考虑到将这些数据类型与其他平台或语言之间的类型进行互相转换问题。打个比方:C++写的客户端发送一个int型(4字节)变量的数据到Python写的服务器,Python接收到表示这个整数的4个字节数据,怎么解析成Python认识的整数呢? Python的标准模块struct就用来解决这个问题。 > > 1. 按照指定格式将Python数据转换为字符串,该字符串为字节流,如网络传输时,不能传输int,此时先将int转化为字节流,然后再发送; > 2. 按照指定格式将字节流转换为Python指定的数据类型; > 3. 处理二进制数据,如果用struct来处理文件的话,需要用’wb’,’rb’以二进制(字节流)写,读的方式来处理文件; > 4. 处理c语言中的结构体; > ### 2.1 struct模块中的函数 函数 return explain #### 2.1.1 pack(fmt,v1,v2…) > 按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回. ~~~ __author__ = 'dailin' import struct # 定义数据 a = b"hello" b = b"world!" c = 20 d = 42.56 # 打包 binStr = struct.pack("5s6sif", a, b, c, d) # 解包 e, f, g, h = struct.unpack("5s6sif", binStr) print (e, f, g, h) ~~~ 输出 ~~~ b'hello' b'world!' 20 42.560001373291016 ~~~ ("5s6sif", a, b, c, d)代表:按照5字符,6个字符,一个整型,一个小数的形式编码,详见格式符 #### 2.1.2 pack_into(fmt,buffer,offset,v1,v2…) None > 按照给定的格式(fmt),将数据转换成字符串(字节流),并将字节流写入以offset开始的buffer中.(buffer为可写的缓冲区,可用array模块) #### 2.1.3 unpack(fmt,v1,v2…..) tuple 按照给定的格式(fmt)解析字节流,并返回解析结果 #### 2.1.4 pack_from(fmt,buffer,offset) tuple 按照给定的格式(fmt)解析以offset开始的缓冲区,并返回解析结果 #### 2.1.5 calcsize(fmt) size of fmt 计算给定的格式(fmt)占用多少字节的内存,注意对齐方式 格式化字符串 当打包或者解包的时,需要按照特定的方式来打包或者解包.该方式就是格式化字符串,它指定了数据类型,除此之外,还有用于控制字节顺序、大小和对齐方式的特殊字符. #### 2.1.6 对齐方式 > 为了同c中的结构体交换数据,还要考虑c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下 ![](https://box.kancloud.cn/f16880a1855488ce6ff80a32fbd528a6_853x248.png) #### 2.17 格式符 ![](https://box.kancloud.cn/d828f1e83fec5dd5589a6b6bab8ceff2_852x818.png) ### 2.2 实例 ~~~ # -*- coding: utf-8 -*- ''' 数据格式为 姓名 年龄 性别 职业 lily 18 female teacher ''' import os import struct fp = open('test.bin','wb') # 按照上面的格式将数据写入文件中 # 这里如果string类型的话,在pack函数中就需要encode('utf-8') name = b'lily' age = 18 sex = b'female' job = b'teacher' # int类型占4个字节 fp.write(struct.pack('4si6s7s', name,age,sex,job)) fp.flush() fp.close() # 将文件中写入的数据按照格式读取出来 fd = open('test.bin','rb') # 21 = 4 + 4 + 6 + 7 print(struct.unpack('4si6s7s',fd.read(21))) fd.close() ~~~ 结果: ~~~ (b'lily', 18, b'female', b'teacher') ~~~