流畅的python第九章符合Python风格的对象学习记录

流畅的python第九章符合Python风格的对象学习记录

流畅的python第九章符合Python风格的对象学习记录

对象表示形式

每门面向对象的语言至少都有一种获取对象的字符串表示形式的标准方式。Python提供了两种方式

repr()便于开发者理解的方式返回对象的字符串表示形式

str()便于用户理解的方式返回对象的字符串表示形式

要实现__repr__,__str__特殊方法为repr(),str()提供支持

流畅的python第九章符合Python风格的对象学习记录

classmethod和staticmethod

classmethod通常用来定义操作类,而不是操作实例的方法。改变了调用方法的方式,因此,类方法的第一个参数是类本身,而不是实例,classmethod最常见的用途是定义备选构造方法

staticmethod装饰器也会改变方法的调用方式,但是第一个参数不是特殊的值,其实,静态方法就是普通的函数,只是碰巧在类的定义体中,而不是在模块层中定义。

流畅的python第九章符合Python风格的对象学习记录

格式化显示

自定义__format__方法,如果没有定义,会返回从object继承的str(my_object)方法

可散列

自定义__hash__方法和__eq__方法

Python的私有属性和受保护的属性

python不能像java那样使用private修饰符创建私有属性,但是有个简单的机制可以避免子类意外覆盖私有属性

流畅的python第九章符合Python风格的对象学习记录

流畅的python第九章符合Python风格的对象学习记录

使用__slots__类属性节省空间

流畅的python第九章符合Python风格的对象学习记录

流畅的python第九章符合Python风格的对象学习记录

流畅的python第九章符合Python风格的对象学习记录

覆盖类属性

流畅的python第九章符合Python风格的对象学习记录

from array import array
import math


class Vector2d:
    typecode = 'd'

    def __init__(self, x, y):
        self.__x = float(x)
        self.__y = float(y)

    @property
    def x(self):
        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):
        class_name = type(self).__name__
        return '{}({!r}, {!r})'.format(class_name, *self)

    def __str__(self):
        return str(tuple(self))

    def __bytes__(self):
        return (bytes([ord(self.typecode)]) + bytes(array(self.typecode, self)))

    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, format_spec=''):
        if format_spec.endswith('p'):
            format_spec = format_spec[:-1]
            coords = (abs(self), self.angle())
            outer_fmt = '<{}, {}>'
        else:
            coords = self
            outer_fmt = '({}, {})'
        components = (format(c, format_spec) for c in coords)
        return outer_fmt.format(*components)

    def __hash__(self):
        return hash(self.x) ^ hash(self.y)

    def angle(self):
        return math.atan2(self.y, self.x)

@classmethod
def frombytes(cls, octets):
    typecode = chr(octets[0])
    memv = memoryview(octets[1:]).cast(typecode)
    return cls(*memv)