Python中常见的特殊方法-魔术方法介绍
程序员文章站
2022-03-27 13:34:04
class Vector2d: ...: typecode = 'd' ...: def __init__(self,x,y): ...: self.__x = float(x) # 私有变量 ...: self.__y = float(y) ...: @property ...: def x(self): ...: # 读取,v1.x相同方式读取 ...: ....
class Vector2d:
...: typecode = 'd'
...: def __init__(self,x,y):
...: self.__x = float(x) # 私有变量
...: self.__y = float(y)
...: @property
...: def x(self):
...: # 读取,v1.x相同方式读取
...: return self.__x
...: @property
...: def y(self):
...: return self.__y
...: def __iter__(self):
...: return (i for i in (self.x,self.y))
...: def __repr__(self):
# eval(repr(v1))==v1
...: class_name = type(self).__name__
...: return '{}({!r},{!r})'.format(class_name,*self)
...: def __str__(self):
# print调用该方法
...: return str(tuple(self))
...: def __bytes__(self):
# 转为字节码
...: return (bytes([ord(self.typecode)]) + bytes(array(self.typecode,self)))
...: @classmethod
...: def from_bytes(cls,octets):
# Vector2d.from_bytes(bytes(v1)) == v1
...: typecode = chr(octets[0])
...: memv = memoryview(octets[1:]).cast(typecode) # memoryview是数组的一种
...: return cls(*memv)
...: def __eq__(self,other):
# 注意特性[3.0,4.0] == print(v1)
...: return tuple(self) == tuple(other)
...: def __abs__(self):
# 计算模长
...: return math.hypot(self.x,self.y)
def __bool__(self):
# bool(v1),若abs(v1)==0则返回Flase
...: return bool(abs(self))
...: def angle(self):
...: return math.atan2(self.y,self.x)
...: def __format__(self,fmt_spec=''):
# 极坐标形式
...: if fmt_spec.endswith('p'):
...: fmt_spec = fmt_spec[:-1]
...: cood = (abs(self),self.angle())
...: outer_fmt = '<{},{}>'
...: else:
...: cood = self
...: outer_fmt = '({},{})'
...: components = (format(c,fmt_spec) for c in cood) # 数字的小格式
...: return outer_fmt.format(*components)
...: def __hash__(self):
# 散列化
...: return hash(self.x)^hash(self.y)
class Vector:
...: typecode = 'd'
...: def __init__(self,components):
...: self._components = array(self.typecode,components)
...: def __iter__(self):
...: return iter(self._components)
...: def __repr__(self):
...: components = reprlib.repr(self._components) # 将超长变量变成...
...: components = components[components.find('['):-1] # 将数组形式进行提取,find函数返回位置
...: return 'Vector({})'.format(components)
...: def __str__(self):
...: return str(tuple(self))
...: def __bytes__(self):
...: return (bytes([ord(self.typecode)])+bytes(self._components))
...: def __hash__(self):
...: hashes = map(hash,self._components)
...: return functools.reduce(operator.xor,hashes,0)# 异或运算需要设置0为初始值,以防报错
...: def __eq__(self,other):
...: return (len(self)==len(other)) and all(a==b for a,b in zip(self,other))
...: def __abs__(self):
...: return math.sqrt(sum(x*x for x in self))
...: def __bool__(self):
...: return bool(abs(self))
...: def __len__(self):
...: return len(self._components)
...: def __getitem__(self,index):
...: # 定义了该方法和len方法就是实现鸭子类型,序列
...: cls = type(self)# 备用
...: if isinstance(index,slice):
...: return cls(self._components[index]) # 如果是切片则返回实例对象
...: def __getattr__(self,name):
...: # 当属性查找失败的时候会调用该方法
...: cls = type(self)
...: if len(name)==1:
...: pos = cls.shortcut_names.find(name)
...: if 0<=pos<len(self.shortcut_names):
...: return self._components[pos]
...: msg = '{.__name__!r} object has no attribute {!r}'
...: raise AttributeError(msg.format(cls,name))
...: def __setattr__(self,name,value):
...: # 防止赋值导致的不一致,与getattr配套使用
...: cls =type(self)
...: if len(name)==1:
...: if name in cls.shortcut_names:
...: error = 'readonly attribute {attr_name!r}'
...: elif name.islower():
...: error = "can't set attributes 'a' to 'z' in {cls_name!r}"
...: else:
...: error = ''
...: if error:
...: msg = error.format(cls_name=cls.__name__,attr_name=name) # 根据错误直接赋值
...: raise AttributeError(msg)
...: super.__setattr__(name,value) # 无error把子类方法委托给超类,必须这么做
...: def angle(self,n):
...: r = math.sqrt(sum(x*x for x in self[n:]))
...: a = math.atan2(r,self[n-1])
...: if (n==len(self)-1) and (self[-1]<0):
...: return math.pi*2 -a
...: else:
...: return a
...: def angles(self):
...: # 计算角度和模
...: return (self.angle(n) for n in range(1,len(self)))
...: def __format__(self,fmt_spec=''):
...: if fmt_spec.endswith('h'):
...: fmt_spec = fmt_spec[:-1]
...: coords = itertools.chain([abs(self)],self.angles()) # 返回一个迭代序列
...: out_fmt = '<{}>'
...: else:
...: coords = self
...: out_fmt = '({})'
...: components = (format(c,fmt_spec) for c in coords)
...: return out_fmt.format(','.join(components))
...: @classmethod
...: def frombytes(cls,octets): # 类方法的第一个参数必定是cls
...: typecode = chr(octets[0])
...: memv = memoryview(octets[1:]).cast(typecode)
...: return cls(memv) # 返回一个类对象,不再拆包
本文地址:https://blog.csdn.net/weixin_40539952/article/details/107382510