流畅的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]

运行结果:

流畅的python第2版 网盘 流畅的python在线阅读_python

流畅的python第2版 网盘 流畅的python在线阅读_内置函数_02

流畅的python第2版 网盘 流畅的python在线阅读_python_03

  定义了__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))