前言:
不要检查它是不是鸭子、它的叫声像不像鸭子、它的走路姿势像不像鸭子,等等。具体检查什么取决于你想使用语言的哪些行为。
目录:
正文:
一. 内容回顾
1.1 Vector类:用户定义的序列类型
1.2 Vector类第1版:与Vector2d类兼容
承接上篇文章:流程的Python 第九章:符合Python风格的对象 对应类内置函数的改写,Vector类将初始化参数改为列表。
# -*- coding:utf-8 -*-
from array import array
import math
class Vector:
def __init__(self, components):
self._components = array('d', components)
def __iter__(self):
return iter(self._components)
def __repr__(self):
return 'Vector'
def __abs__(self):
return math.sqrt(sum(x * x for x in self))
def __eq__(self, other):
return tuple(self) == tuple(other)
def __bytes__(self):
return "bytes"
def __bool__(self):
return bool(abs(self))
def show_data(self):
print self._components
if __name__ == '__main__':
myVector = Vector([3, 4, 6])
print myVector
print abs(myVector)
print myVector == [3, 4]
print bytes(myVector)
print bool(myVector)
myVector.show_data()
1.3 协议和鸭子类型
1.4 Vector类第2版:可切片的序列
# -*- coding:utf-8 -*-
from array import array
import numbers
class Vector:
def __init__(self, components):
self._components = array('d', components)
def __len__(self):
return len(self._components)
def __getitem__(self, index):
cls = type(self)
if isinstance(index, slice):
return cls(self._components[index])
elif isinstance(index, numbers.Integral):
return self._components[index]
else:
msg = '{cls.__name__} indices must be int'
raise TypeError(msg.format(cls=cls))
class MyVector:
def __init__(self, components):
self._components = list(components)
def __len__(self):
return len(self._components)
def __getitem__(self, item):
if isinstance(item, slice):
return self._components[item]
elif isinstance(item, numbers.Integral):
return self._components[item]
else:
msg = '{cls.__name__} indices must be int'
raise TypeError(msg)
if __name__ == '__main__':
vector = Vector(range(7))
# print len(vector)
# print vector[2]
# print vector[-1]
# print vector[2:4]
myVector = MyVector(range(7))
print myVector[2:4]
示例中 return cls(self._components[index])
报错信息如下:
TypeError: must be classobj, not array.array
将array用list替换,进行切片处理。
1.5 Vector类第3版:动态存取属性
# -*- coding:utf-8 -*-
class Vector(object):
shortcut_names="xyzt"
def __init__(self,components):
self._components = components
def __getattr__(self, name):
cls = type(self)
if len(name) == 1:
pos = cls.shortcut_names.find(name)
if 0 <= pos <= len(self._components):
return self._components[pos]
def __setattr__(self, name, value):
cls = type(self)
if len(name) == 1:
if name in cls.shortcut_names:
error = "readonly attributes {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(Vector, self).__setattr__(name, value)
if __name__ == '__main__':
v = Vector(range(7))
print v.y
print v.x
print v.Y
1.6 Vector类第4版:散列和快速等值测试
# -*- coding:utf-8 -*-
import functools
import operator
class Vector:
def __init__(self, components):
self._components = components
def __len__(self):
return len(self._components)
def __eq__(self, other):
return (len(self) == len(other) and
all(a == b for a, b in zip(self._components, other)))
def __hash__(self):
hashes = (hash(x) for x in self._components)
return functools.reduce(operator.xor, hashes, 0)
if __name__ == '__main__':
vector1 = Vector(range(3))
print vector1 == [1, 2]
print vector1 == [0, 1, 2]
print hash(vector1)
a = "timen.xu"
print hash(a)
1.7 Vector类第5版:格式化
# -*- coding:utf-8 -*-
import itertools
class Vector:
def __init__(self, components):
self._components = components
def __format__(self, fmt_spec=''):
if fmt_spec.endswith('h'):
fmt_spec = fmt_spec[:-1]
coords = itertools.chain([abs(self._components)],
self.angles())
outer_fmt = '<{}>'
else:
coords = self._components
outer_fmt = '({})'
components = (format(c, fmt_spec) for c in coords)
return outer_fmt.format(', '.join(components))
if __name__ == '__main__':
print format(Vector(range(9)))
二. 相关资料
2.1 新增_ setattr_方法,当对属性进行赋值的时候,首先会调用_ setattr_方法。在方法中对属性进行判断和保护。
三. 阅读后感
第九章和第十章都在介绍了类的很多内置方法,比如_ add_ , _ eq _等。本书名称为《流程的Python》就是讲Python内置的方法的使用,从而使得Python运行更加快速。
参考:
1. 流畅python学习笔记:第十章:序列的修改,散列和切片