fluent python epub_Fluent Python 笔记(一):数据模型

目录:

前段时间(年前)撸完了 Fluent Python,感觉非常不错,大概是看过的 Python 教材中最好的一本了。想整理一下,由于工作比较忙(懒)一直没时间,现在稍微总结一下(挖个坑)。

首先看两个很酷的例子:

1. 用 Python 表示一副扑克牌

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDeck:

ranks = [str(n) for n in range(2, 11)] + list('JQKA')

suits = 'spades diamonds clubs hearts'.split()

def __init__(self):

self._cards = [Card(rank, suit) for suit in self.suits

for rank in self.ranks]

def __len__(self):

return len(self._cards)

def __getitem__(self, position):

return self._cards[position]

2. 用 Python 表示二维向量

from math import hypot

class Vector:

def __init__(self, x=0, y=0):

self.x = x

self.y = y

def __repr__(self):

return 'Vector(%r,%r)' % (self.x, self.y)

def __abs__(self):

return hypot(self.x, self.y)

def __bool__(self):

return bool(abs(self))

def __add__(self, other):

x = self.x + other.x

y = self.y + other.y

return Vector(x, y)

def __mul__(self, scalar):

return Vector(self.x * scalar, self.y * scalar)

这两个例子个人觉得都算是比较优雅的。其中最关键的一点是,Python 中的特殊函数形式都是 __xxx__ ,想要一个对象能够“做一件很多类都能做的事”,只需要实现对应的特殊函数就行了。(后面还会说明,Python 中的一些特性,如切片,多维数组,也都是特殊函数的语法糖)实现了 __len__ 就可以对其调用 len() 函数

>>> deck = FrenchDeck()

>>> len(deck)

52实现了 __getitem__ 就可以对其索引

>>> deck[0]

Card(rank='2', suit='spades')

>>> deck[-1]

Card(rank='A', suit='hearts')想要把一个类表示为字符串,有两个方法,__str__ 和 __repr__。

前者的目标是可读性,(看一眼里面我所关心的变量值是什么),后者的目标是明确性(用这个字符串可以创建完整的类 eval(repr(c)) == c)。

print方法会首先查找一个对象的 __str__ 方法,如果没找到则 fallback 到__repr__。

也可以指定 %s 格式化,使用 __str__ 方法,指定 %r 格式化,使用 __repr__ 方法。(一般来说,__str__ 就够用了)实现 __add__ 用于加法,__mul__ 用于乘法,__rmul__ 用于右乘

在一个需要判断对象x为 True 或者 False 的环境中(if, while...),Python会调用 bool(x)。

bool(x)首先调用 x.__bool__(),如果没有该方法则调用 x.__len__(),返回0就是 False,否则就是 True。

对 Python 的基本类型进行布尔判定时,是有规律可循的,基本上你觉得应该是 False 的,那么就是 False。比如数值0,空字符串,空列表,空集合等等,除此之外都是 True。(前两天有同学表示不知道 0 是 True 还是 False,我还是挺惊讶的)

常用特殊函数一览表:

非操作符重载类:

操作符重载类:

总结:

本文主要介绍了 Python 的“体制内”函数(雾)。实现一个 Python 类的时候,可以首先考虑遵循体制内潜规则,这样便可以获得体制内福利。换句话说,实现了某个特殊函数不仅仅代表着支持对应功能,还意味着所有适用于相似内置类型的函数,都可以直接拿来用。在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。

理解了这个,就能更好地理解 Python 内置类型的设计规律。

你可能感兴趣的:(fluent,python,epub)