-
Notifications
You must be signed in to change notification settings - Fork 3
Fluent Python读书笔记(八)
除了这两个特殊函数之外, 还有 __bytes()__
和__format()__
. __repr()__
,__str()__
和__format()__
应该返回unicode字符串; __bytes()__
返回字节序列
__format()__
用于format()函数的调用. format标识符用在两个地方
- format(my_obj, format_spec)函数的第二个参数
- str.format()函数中
{}
类的参数
如果一个类没有定义__format()__
方法, 则会使用__str()__
方法替代. 但如果要使用format标识符, 则一定要定义__format()__
方法
classmethod的第一个参数为cls, 一般用于对构造函数的改造或初始化. staticmethod类似于模块中的普通函数, 只不过在类中定义.其第一个参数不要求为self或cls
使用@property装饰器. **注意, 根据Python Cookbook说明, @property装饰器是个类装饰器, 包含getter(),setter()和deleter()**三个方法.
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 __hash__(self):
return hash(self.x) ^ hash(self.y)
def __abs__(self):
return math.hypot(self.x, self.y)
def __bool__(self):
return bool(abs(self))
def angle(self):
return math.atan2(self.y, self.x)
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
outer_fmt = '({}, {})'
components = (format(c, fmt_spec) for c in coords)
return outer_fmt.format(*components)
@classmethod
def frombytes(cls, octets):
typecode = chr(octets[0])
memv = memoryview(octets[1:]).cast(typecode)
return cls(*memv)
Python不像Java一样,有严格的私有或保护属性. python规定以__
(两个下划线)开头的属性是私有属性, 会转变成_<className>__<attr>
的形式保存在__dict__
属性中.
以_
(单个下划线)开头的变量在python中没有特殊的处理, 这只是一个使用惯例, 表示保护变量.
默认情况下, python对于实例的属性存放在对象内部的__dict__
属性中,dict内部含有稀疏矩阵的哈希表. 因此对于大量实例情况下会非常占用内存空间. 这种情况下, 我们就可以使用__slot__
. 当定义了slots后,slots中定义的变量变成了类的描述符,相当于java,c++中的成员变量声明,类的实例只能拥有这些个变量,而不再有dict,因此也就不能再增加新的变量
__slots__
也有些使用限制:
-
__slots__
不继承, 必须在每个需要的类中作为类变量定义 -
不允许不在
__slot__
中的实例属性存在.class A: __slots__=['name'] def __init__(self): self.name='js' self.age=22 a=A() #报错. age不在__slots__中存在
也可以把
__dict__
存放在__slots__
中,这样就可以定义动态属性了class A: __slots__=('name','city','__dict__') #将__dict__放入__slots__中 def __init__(self): self.name='js' self.age=22 #可以定义age实例属性了. a=A()
-
除非定义
__weakref__()
方法, 否则对象不能作为weakref引用对象, 因为定义__slot__
后也取消了__weakref__
的生成