Fluent Python学习笔记——CH1 Python 数据模型

文章目录

          • 一、主要知识点:
            • 1. collections.namedtuple
            • 2. 魔法(特殊)方法在自定义类中的实现
          • 二、代码部分
            • 1. 一摞有序的纸牌
            • 2. 一个简单的二维向量类
        • Reference

一、主要知识点:
1. collections.namedtuple
2. 魔法(特殊)方法在自定义类中的实现
  1. __getitem__ 妙用
  2. __repr__ 和 __str__ 的区别
二、代码部分
1. 一摞有序的纸牌
# 1.1 一摞有序的纸牌
import collections
from random import choice

Card = collections.namedtuple("Card", ["rank", "suit"])
suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)


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 rank in self.ranks for suit in self.suits]

    def __len__(self):
        return len(self._cards)

    # __getitem__ in builtins: return self[key]
    # 通过实现 __getitem__ 方法,可以将对象变成可迭代对象
    def __getitem__(self, position):
        return self._cards[position]


def spades_high(card):
    rank_value = FrenchDeck.ranks.index(card.rank)
    return rank_value * len(suit_values) + suit_values[card.suit]


deck = FrenchDeck()
for card in sorted(deck, key=spades_high, reverse=True):
    print(card)

2. 一个简单的二维向量类
# 特殊方法的存在是为了被 Python 解释器调用的,自己并不需要调用它们。 
# 没有 my_object.__len__() 这种写法,而应该使用 len(my_project)。
# 在执行 len(my_object) 的时候,若该对象是一个自定义类的对象,Python 会自己去调用其中由你自己实现的 __len__ 方法。
# 除非有大量的元编程存在,通常代码无需直接使用特殊方法,直接调用特殊方法的频率应该远远低于实现它们的次数。(不要随意添加特殊方法)

# 1.2.1 一个简单的二维向量类
from math import hypot


class Vector:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    # __repr__: 字符串表示形式,如果没有实现 __repr__,打印一个向量的实例可能会显示 
    # __repr__ 返回的字符串应当准确、无歧义,且尽可能表达出如何用代码创建出这个被打印的对象,e.g. Vector(3, 5)
    # __repr__ vs __str__:
    # 1. 前者表述更明确清晰,方便调试和记录日志;
    # 2. 后者返回的字符串易读,对终端用户更友好,适合输出给用户
    # 3. 如果只能取其一,推荐选择 __repr__
    def __repr__(self):
        return "Vector(%r, %r)" % (self.x, self.y)  # %r 获取对象各个属性的标准字符串表示形式

    def __abs__(self):
        return hypot(self.x, self.y)

    # 对于判定一个值 x 为真还是为假,Python 会调用 bool(x),该函数将返回 True or False
    # bool(x) 背后调用的是 x.__bool__() 的结果,若不存在 __bool__ 方法,则 bool(x) 尝试调用 x.__len__()
    # 默认情况下,自定义类的实例总被认为是真的,除非对 __bool__ 或 __len__ 有自己的实现
    def __bool__(self):
        return bool(abs(self))  # 在此,通过判断向量的模是否为 0 来判断 Vector 的布尔值
        # return bool(self.x or self.y)  # more efficient realization while not straightforward

    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)

Reference

[1] Ramalho L. Fluent Python: Clear, concise, and effective programming[M]. " O’Reilly Media, Inc.", 2015.
[2] Fluent Python (2nd Edition)
[3] Fluent Python 2e example code

你可能感兴趣的:(Fluent,Python,学习笔记,python,学习,开发语言)