python学习笔记7-符合python风格的对象

1.例
from array import array
import math

class Vector2d:

typecode = 'd'#类属性 

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

def __iter__(self):# 将实例变为可迭代的对象 以实现拆包 调用生成器 
	return (i for i in (self.x, self.y)) # return (self.x, self.y)

def __repr(self):#使用{!r}获取两个值 *self拆分x,y
	class_name = type(self).__name
	return '{}({!r}, {!r})'.format(class_name, *self)

def __str__(self):#这是的Vector2d已经是可迭代对象了 所以可以直接得到一个元组
	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 __bool__(self):
	return bool(abs(self))

2.例 这是上例的一部分补充 也在类中定义
@classmethod
def frombytes(cls, octets):#不用传入self参数 相反需要通过cls来传入类本身
typecode = chr(octets[0])
memv = memoryview(octets[1:]).cast(typecode)
return cls(*memv)#拆包memoryview 得到构造方法需要的一堆参数

2.解释classmethod
要放在类中
定义操作类的方法 而不是操作实例的方法
第一个参数就是类本身 而不是实例

3.利用以上的装饰器来进行格式化显示
首先补充format用法
(1) print(’{name}在{option}’.format(name = ‘某人’, option = ‘写代码’)) 关键字
(2) print(‘name={} path={}’.format(‘张三’, ‘/’)) 位置
(3) print(’{1}在{0}’.format(‘写代码’, ‘某人’)
(4) print(’{num:.2f} is {num1:.5f}’.format(num = 3.1415, num1 = 3.14159265358979323846))

from datetime import datetime
now = datetime.now()
format(now, ‘%H:%M:%S’)

format(42, ‘b’)

4.我们想让编写的Vector2d也可以由format来格式化显示
比如 format(v1, ‘.2f’)
于是在前两条的Vector2d中加入
def format(self, fmt_spec = ’ '):
components = (format(c, fmt_spec) for c in self)#此时实现了类的可迭代 所以直接调用self 表示这个可迭代对象
return ‘({}, {})’.format(*component)#对于接受多个参数的函数或者定义式都可以用拆分的方式直接赋值 但是要注意一一对应

5.再为向量类 添加角度
def angle(self):
return math.atan2(self.y, self.x)
再次改进向量类的format
def format(self, fmt_spec = ’ '):
if fmt_spec.endswith(‘p’):#极坐标
fmt_spec = fmt_spec[:-1]
coords = (abs(self), self.angle())#调用其他函数
outer_fmt = ‘<{}, {}>’
else:
coords = self#当类是可迭代对象时 直接使用self表示这个可迭代对象
#可以赋值 可以进行迭代
outer_fmt = ‘({}, {})’
components = (format(c, fmt_spec) for c in coords)
return outer_fmt.format(*components)

6.可散列的Vector2d
现在的实例 v1.x = 7 可以直接给分量赋新值
我们想实现它的只读性 不可以随意修改
同时这个向量类的散列性 需要实现__hash__方法和__eq__方法
把x和y设为只读特性
class Vector2d:
typecode = ‘d’

def __init__(self):
	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))

使得向量不可变 就可以求hash值
例:
def hash(self):
return hash(self.x) ^ hash(self.y)

7.Python的私有属性和受保护属性
因为可能会发生没有开放的实例属性在继承时再次创建 导致被覆盖的情况
self.__x 使得变为私有属性 会添加到 __dict__中
显示为_类名__x 这是名称改写
(1)另一种习惯是在属性前加 _ 解释器不会注意 但这是一种习惯 表示不要在类外部访问这种属性

8.使用__slots__类属性节省空间
python在各个实例中名为__dict__的字典里存储实例属性
使用__slots__类属性 告诉解释器 这个类中的所有实例属性都在这里
例如
class Vector2d:
slots = (’__x’, ‘__y’)
typecode = ‘d’
注意事项:子类也要定义__slots__属性 不会继承
实例只能拥有__slots__中列出的属性
__slots__不加入’weakref’就不能作为弱引用的目标

9.python中类属性可以为实例属性提供默认值
比如实例属性没有 但是有同名类属性 则会取类属性的值
这时给不存在的实例属性赋值 会新建实例属性 并不再使用类属性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值