符合Python风格的对象
array和bytes的转换
- 每个array必须有一个type_code,以此为依据解析底层字节序列
- array有一个frombytes方法,可以把字节序列按type_code转换成Array
- bytes构造函数接受一个可迭代对象作为参数,它依次遍历可迭代对象,将每个元素按其本身的数据类型拆成字节
from array import array def create_bytes(): type_code = 'f' # ord函数返回字符的编码 print('type_code:',ord(type_code)) ar = array(type_code,[0.19,0.23]) # bytes构造函数接受一个可迭代对象作为参数 # 它依次遍历可迭代对象,将每个元素拆成字节 # type_code1个字节,float4个字节,一共9个字节 by = bytes([ord(type_code)]) + bytes(ar) print('bytes(len:%d):' % len(by), by) return by def from_bytes(by): # 将第一个字节转换为字符 type_code = chr(by[0]) # 以后的每4个字节转换为一个float # 先用type_code构造一个Array arr = array(type_code) # 再把字节序列按type_code转换成Array arr.frombytes(by[1:]) print(arr) bytes = create_bytes() from_bytes(bytes) 输出: type_code: 102 bytes(len:9): b'f\\\x8fB>\x1f\x85k>' array('f', [0.1899999976158142, 0.23000000417232513])
classmethod和staticmethod
class Demo: @classmethod def klassmethod(*args): print(args) @staticmethod def statmethod(*args): print(args) # classmethod自动将类作为第一个参数传入 Demo.klassmethod() Demo.klassmethod('param') # staticmethod只是定义在类中的一个普通方法 Demo.statmethod() Demo.statmethod('param') 输出: (<class '__main__.Demo'>,) (<class '__main__.Demo'>, 'param') () ('param',)
对象散列相关方法
- 首先要保证对象不可变
- 其次要实现hash和eq方法
class Vector2d: def __init__(self,_x,_y): self._x = float(_x) self._y = float(_y) def __iter__(self): return (item for item in (self.x,self.y)) # 用propery装饰器设置只读属性,保持对象的不可变 @property def x(self): return self._x @property def y(self): return self._y # 使对象可散列 def __hash__(self): return hash(self.x) ^ hash(self.y) # 可散列的同时,还要实现相等方法 def __eq__(self, other): return self.x == other.x and self.y == other.y v1 = Vector2d(3,4) v2 = Vector2d(3,4) print(hash(v1),hash(v2),v1==v2) 输出: 7 7 True
Python的私有属性
class Dog: def __init__(self,name): # 如果以__var的形式命名实例属性,Python会把属性名存入实例的__dict__属性中 # 而且会在前面加上一个下划线和类名 self.__name = name dog = Dog('Bob') print(dog.__dict__) # 'Dog' object has no attribute '__name' # print(dog.__name) print(dog._Dog__name) 输出: {'_Dog__name': 'Bob'} Bob
使用__slots__类属性
- 用法
- 创建__slots__类属性,把值设置为一个属性名称(字符串)构成的可迭代对象
- 好处:
- 可以避免使用消耗内存的__dict__属性,从而节约内存
- 不允许实例动态创建其他的属性
class Vector2d: __slots__ = ('_x','_y') def __init__(self,_x,_y): self._x = float(_x) self._y = float(_y) v2d = Vector2d(1,2) # 'Vector2d' object has no attribute '__dict__' # print(v2d.__dict__) # 'Vector2d' object has no attribute 'z' # v2d.z = 'z'
- 注意点
- 如果把 '__dict__' 这个名称添加到__slots__中,实例会在元组中保存各个实例的属性,此外还支持动态创建属性
- 为了让对象支持弱引用,需要再__slots__中放__weakref__属性
- 每个子类要定义自己的__slots__属性,继承无效
class Vector2d: __slots__ = ('_x','_y','__dict__') def __init__(self,_x,_y): self._x = float(_x) self._y = float(_y) v2d = Vector2d(1,2) v2d.z = 'z' print(v2d.__dict__) 输出: {'z': 'z'}