Fluent Python 读书笔记01 Python数据模型

Chapter 01 The Python Data Model

一叠Python风格的纸牌

先用一个例子来演示__getitem____len__魔法方法。

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]
  • 用nametuple来创建对象的类,不需要用自定义的方法来绑定属性
  • 可以响应len()函数返回卡牌数量(__len__)
>>>deck = French()
>>>len(deck)
52
  • 可以索引指定的牌,这是__getitem__方法提供的
>>>deck[0]
Card(rank="2", suit="spides")
>>>deck[-1]
Card(rank="A", suit="hears")
  • 纸牌也是可以迭代的(__getitem__)
>>>for card in deck():
...     print(card)
Card(rank="A", suit="hearts")
...
  • 因为可以迭代(iterable),解包操作也是支持的(__getitem__)
>>>from random import choice
>>>card1 = choice(deck)
>>>x, y = card1
>>>x, y
"7", "spades"
  • __getitem__方法给slef._cards授权了[]操作,我们的卡牌支持切片操作。
>>>deck[:3]
  • 迭代通常是隐形的。如果一个集合类型没有__contains__方法,那么in操作符会对进行一次序列性扫描(a sequential scan)。(__getitem__)
>>>Card("Q", "hearts") in deck
True

怎样使用魔法方法

魔法方法是Python解释器调用的,而不是通过你。不需要写my_object.__len__()这种写法,写len(my_object),Python会调用__len__

对于内置的类型,比如list, str, bytearray等等,解释器会使用更快捷的方式而不是魔法方法,因为这样更快。比如在CPython的len()的实现实际上是返回在PyVarObjectC结构体里的ob_size字段的值,PyVarObject是内存中任意可变长度的内置对象。
对于len为什么不是一个方法,核心开发者Raymond Hettinger的解释是:practicality beats purity。实用胜于纯粹。获取集合类型的元素数量是一个通用操作而且对于这些基本的类型,需要更加高效。

通常情况下,魔法方法的调用是隐性的。比如,for i in x语句,实际上调用iter(x),在这背后的实现是x.__iter__(),前提是这个方法实现了(前面没有__iter__没有实现而是用__getitem__)

当没有自定义的__str__方法时,会调用__repr__作为替代,所以在__str____repr__方法里只能选择一个的话,选择__repr__

模拟数学类型

再来另一个例子,用一个类来实现二维向量的表示

from math import hypot


class Vector:

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

    def __repr__(self):
        return f"Vector({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)

分析一下:

  • 重载__repr__,当我们使用print的时候,调用的是str(),也就是__str__,这里我们没有重载__str__方法,这样print会调用__repr__
>>>v1 = Vector(2, 4)
>>>v2 = Vector(2, 1)
>>>v1  # 调用__repr__()
Vector(2, 4)
>>>print(v1)  # 没有__str__,调用__repr__()
Vector(2, 4)
  • 重载__add____mul__,这两个方法背后是+, *操作符:
>>>v1 + v2
Vector(4, 5)
>>>v1 * 3
Vector(6,  12)
# 3 * v1和v1 * v2是报错的,具体我还没会
# TypeError: unsupported operand type(s) for *: 'int' and 'Vector'
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 走遍了南北西东,也到过了许多名城......还是会在一个人慢慢散步的时候想起家。 当同事放假过节欢快的回家时,我就...
    温暖大大白阅读 260评论 0 0
  • 之前我一直觉得币圈跟现实生活是两个不大相干的世界。在自己的实际交际圈中,只有我一个人在投资数字货币,虽然早前我有推...
    思颖hurry阅读 147评论 0 0
  • 因为明天要陪大宝去上海,应老爸老妈嘱咐去他们那里吃饭,记录发生的两件事情。 场景一: 老人家照例烧了一大桌子的菜,...
    Hao思嘉阅读 254评论 0 0
  • 阳光明媚,春暖花开!晴朗的天气,总让人觉得心清气爽。美丽的花儿让寒冷枯凌的冬季悄然离去!
    水木幻城阅读 402评论 0 0