导语:本文章记录了本人在学习Python基础之面向对象篇的重点知识及我的心得,打算入门Python的朋友们能够来一块儿学习并交流。
本文重点:python
一、掌握编写Pythonic code背后经常使用的特殊方法;
二、掌握可扩展的格式化输出方法;
三、了解可散列对象的设置以及节省内存的__slots__对象。
自定义的向量类须要支持基本的输出,迭代,求模。程序员
从自定义向量类型入手写出符合Python风格的对象,这离不开特殊方法的支持。
咱们指望的自定义向量类型应支持的基本功能:数组
代码实现以下:函数
import math from array import array class Vector2d: typecode='d' def __init__(self,x,y): self.x=float(x) self.y=float(y) def __str__(self): return str(tuple(self)) def __iter__(self): return (i for i in (self.x,self.y)) def __repr__(self): classname=type(self).__name__ s="{}({},{})".format(classname,*self) return s def __abs__(self): return math.hypot(self.x,self.y) def __bytes__(self): return (bytes(self.typecode,encoding='utf-8')+ bytes(array(self.typecode,self)))
咱们能将实例转化为字节序列,那么也应构造一个将实例转化为字节序列的方法。学习
@classmethod def frombytes(cls,seqs): typecode=chr(seqs[0]) memv=memoryview(seqs[1:]).cast(typecode) return cls(*memv)
memoryview是泛化和去数学化的数组。code
classmethod:定义操做类而不是操做实例的方法,类方法的第一个参数是类自己而不是实例。最多见的用途是定义备选构造方法(返回cls(*))component
staticmethod:是普通的函数,只是碰巧在类的定义体中,而不是在模块层定义。orm
经过改写format背后的__format__能够写出可扩展的格式。
实例1:实现format对向量类的处理对象
def __format__(self,fmt_spec=''): components=(format(v,fmt_spec)for v in self) return "({},{})".format(*components)
实例2:经过尾部自定义格式代码p实现将直角坐标向量转化为极坐标向量。继承
def __format__(self,fmt_spec=''): if fmt_spec[-1]=="p": coord=(abs(self),self.angle()) spec=fmt_spec[:-1] components=(format(v,spec)for v in coord) outer="<{},{}>" else: coord=self components = (format(v, fmt_spec) for v in self) outer = "({},{})" return outer.format(*components)
本段代码的重点在于判断格式中是否存在自定义格式符p,并进行对应的格式处理。
目前的向量是不可散列的,而可散列对象须要知足:
(1)支持hash()函数,而且经过hash()获得的散列值是不变的; (2)支持经过__eq__()方法来检测相等性; (3)若a==b为真,则hash(a)=hash(b)也为真。
因此咱们须要把对象定为不可变,而后自定义__hash__。
经过使用两个前导下划线。将属性标记为私有的。
@property def x(self): return self.__x @property def y(self): return self.__y
使用异或运算符实现。
def __hash__(self): return hash(self.x)^hash(self.y)
Python程序员约定使用一个下划线前缀编写“受保护”的属性即self._x
,他们认为应该使用命名约定来避免意外覆盖属性。默认状况下,Python在各个实例中名为__dict__的字典中储存实例属性,相应地会消耗大量内存。经过__slots__类属性,并让解释器把实例属性存储在元组中,能够节省大量内存。
class Vector2d: __slots__ = ('__x','__y') typecode='d' #其余方法实现省略
使用__slots__应注意的问题:
当处理的实例规模较小时,禁止建立动态属性或不支持弱引用是比较好的选择。
经过建立子类能够把继承自父类的实例属性覆盖掉。
class Shortvector2d(Vector2d): typecode = 'f' #其它方法实现省略