流畅的Python——符合Python风格的对象

符合Python风格的对象

定义一个Python风格的向量类,让它:

  • 支持用于生成对象其他表示形式的内置函数(通过定义__repr____format__函数实现);
  • 使用一个类方法实现备选构造方法;
  • 扩展内置的format()函数和str.format()方法使用的格式微语言(如,可以通过指定format(Vector, 'p')来输出向量的极坐标表示形式);
  • 实现只读属性;
  • 把对象变成可散列的,通过给出正确__hash__方法定义;
  • 利用__slots__节省内存(此处略)。
from array import array
import math

class Vector2d:
    typecode = 'd'
    
    def __init__(self, x, y):
        self.__x = float(x) #使用双下对类属性进行标记,将其标记为私有的
        self.__y = float(y) #使用双下对类属性进行标记,将其标记为私有的
    
    @property     #property装饰器将读值方法标记为特性,读值方法与公开属性同名
    def x(self):
        return self.__x
    
    @property
    def y(self):
        return self.__y
    
    def __hash__(self): #实现了__hash__和__eq__方法之后,可以是Vector类对象变为可散列的.
        return hash(self.x) ^ hash(self.y)
    
    def __iter__(self):
        return (i for i in (self.x, self.y)) #定义__iter__方法,将vector2d变为可迭代对象,
        #这样做才能对vector2d对象进行拆包分解, 如 x, y = Vector2d这样的语句是合法的
    
    def __repr__(self):
        class_name =  type(self).__name__
        return '{}({!r},{!r})'.format(class_name, *self)
        #__repr__方法使用{!r}获取各个分量的表示形式, 然后插值, 构成一个字符串. 由于Vector2d
        #实例是可迭代对象, 因此*self会把x和y分量提供给format函数
    
    def __str__(self):
        return str(tuple(self))
    
    def __bytes__(self):
        return (bytes([ord(self.typecode)]) + bytes(array(self.typecode, self))) 
        #将Vector2d实例转化为字节序列
    
    def __eq__(self, other):
        return tuple(self) == tuple(other) #既可以视作特性, 也可以视作缺陷
    
    def __abs__(self):
        return math.hypot(self.x, self.y) #计算绝对值即求这个向量的模长
    
    def __bool__(self):
        return bool(abs(self))
    
#     def __format__(self, fmt_spec=''):
#         components = (format(c, fmt_spec) for c in self) #使用python内置的format函数,将fmt_spec格式通过迭代的方法应用到两维的变量上
#         return '({}, {})'.format(*components)            #再通过str.format进行格式化输出
    
    def angle(self):
        return math.atan2(self.x, self.y)
    
    def __format__(self, fmt_spec):
        if fmt_spec.endswith('p'):  #现在可以使用format(v,'p')的方式,以极坐标的形式格式化输出向量
            fmt_spec = fmt_spec[:-1]
            coords = (abs(self), self.angle)
            outer_fmt = '<{}, {}>'
        else:
            coords = self
            outer_fmt = '({}, {})'
        
        components = (format(c, fmt_spec) for c in coords)
        return outer_fmt.format(*components)
    
    @classmethod #通过frombytes将字节序列转化为Vector2d。
    #使用装饰器classmethod,实现了备选构造方法
    def frombytes(cls,octets):
        typecode = chr(octets[0])
        memv = memoryview(octets[1:]).cast(typecode)
        return cls(*memv)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值