流畅的python阅读笔记——第一章 Python数据模型
前言
最近疫情被关起来了,比较闲。准备读一读《流畅的python》,做一做笔记,提高一下python编程能力。这本书针对python进阶阶段的读者。和其他的进阶书不同,这本书主要是针对python语言和风格本身的进阶,而不是python在网络等方便高级包的应用。 这本书读起来还是挺困难的。很多地方我也不是很懂。我尽量边学边查,有些地方简单说一说自己的理解。如果有错误,希望大家批评指正。
本章内容概述
这一章介绍的内容是python面向对象编程的特殊方法。python有很多内置函数,给我们编程带来了极大的便利,也提高了程序效率。类似于C++重载运算符,使用python设计自己的类时,也需要针对这些内置函数和运算符进行“重载操作”。 python内置函数见菜鸟教程。还有+ - * / 这些算术运算符或者逻辑运算符如果需要使用的话,都需要重载。 python特殊方法和内置函数的对应关系,见这位大佬的博客。我在这里主要举几个教材上面的例子。
1.1 一摞Python风格的纸牌
意思就是实现一个表示扑克牌的类 这里用到了一个collections类的namedtuple。collections类是python内建集合模块,实现了许多十分高效的特殊容器数据类型。比如它本来就有list、tuple、dict等等方便的数据类型,但是类里的实现更高效。本节只用到了namedtuple,如果不熟悉在这个博客熟悉一下。
import collections
from math import hypot
from random import choice
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = ['spades', 'diamonds', 'clubs', 'hearts']
#初始化函数
def __init__(self):
self._card = [Card(rank, suit) for rank in self.ranks
for suit in self.suits]
#len()
def __len__(self):
return len(self._card)
#索引、切片和迭代功能
def __getitem__(self, item):
return self._card[item]
运行结果:
定义了__getitem__方法之后,该类就是可索引,可切片,可迭代(for item in 类:)的了。这个random库里的choice也算是内置函数。我理解它只需要使用类的索引,因此我们定义了索引的特殊方法之后就可以利用这个工具了。
如果我们想对上述纸牌类进行排序操作,执行下述代码:
suit_values={"spades":3,"hearts":2,"diamonds":1,"clubs":0}
def spades_high(card):
rank_value=FrenchDeck.ranks.index(card.rank)
return rank_value*len(suit_values)+suit_values[card.suit]
sorted(deck,key=spades_high)
相当于针对纸牌的数字排序,同数字的不同花色之间也要排序。
1.2 特殊方法的使用
这里定义了一个向量类
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
#在控制台输出对象实例
#如果不写这个大概率会输出<Vector object at 0x????>
#这里%现在用的少了,建议用str.format来格式化字符串
#__str__方法是用于print()或str(),__repr__用于控制台直接输出
#但是最好是使用__repr__,使用print如果没有__str__会去找__repr__
def __repr__(self):
return "Vector(%r, %r)" % (self.x, self.y)
#这里的乘法是不满足交换律的。至于反向怎么办,会在后面的章节介绍
def __mul__(self, scale):
return Vector(self.x * scale, self.y * scale)
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Vector(x, y)
def __abs__(self):
return hypot(self.x, self.y)
def __bool__(self):
return bool(abs(self))