专栏首页dongfanger魔法方法推开Python进阶学习大门

魔法方法推开Python进阶学习大门

热爱Python

Python是Guido van Rossum设计出来的让使用者觉得如沐春风的一门编程语言。2020年11月12日,64岁的Python之父宣布由于退休生活太无聊,自己决定加入Microsoft的DevDiv Team,致力于“确保更好地使用Python”。尽管在国内有些声音在Diss着Python,认为它太简单,只是个脚本语言,但是它的发明者对Python的热情,仍然激励着我们坚持对Python的热爱。

龟叔是所有编程语言发明者当中头发最多的这位。

奇迹时刻

collection.len()是面向对象语言的写法,len(collection)是Python语言的写法,这种风格叫做Pythonic。从前者到后者,就像变魔术一样,一瞬间让人眼前一亮。这个魔术就是Python魔法方法,或者叫双下方法,它是用双下划线开头和双下划线结尾的特殊方法,比如obj[key],Python解释器实际上会转换成obj.__getitem__(key)来运行,但是使用者并无感知。

__getitem____len__

__getitem__用来获取数据,__len__用来返回长度,这2个魔法方法是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]

本来我们对这副牌什么都不能做,但是由于实现了__len__,可以使用len()函数查看有多少张牌:

>>> len(deck)
52

由于实现了__getitem__,可以使用中括号索引取值:

>>> deck[0]
Card(rank='2', suit='spades')

能进行切片:

>>> deck[:3]
[Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), Card(rank='4', suit='spades')]
>>> deck[12::13]
[Card(rank='A', suit='spades'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='clubs'), Card(rank='A', suit='hearts')]

能迭代:

>>> for card in deck:  # doctest: +ELLIPSIS
...   print(card)
Card(rank='2', suit='spades')
Card(rank='3', suit='spades')
Card(rank='4', suit='spades')
...

发现没有,魔法方法是可以用来装B的!别人写个类只能getset,你写个类还能花式炫技,666。

Python魔法方法是给Python解释器使用的,一般不需要直接调用,Python会自己去调,比如把len(my_object)写成my_object.__len__(),就弄巧成拙了。

魔法方法实现运算符

前面例子实现了取值和长度,接着再看一个例子,使用__repr____abs____bool____add____mul__,实现运算符:

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)

__add__实现了加法:

>>> v1 = Vector(2, 4)
>>> v2 = Vector(2, 1)
>>> v1 + v2
Vector(4, 5)

__abs__实现了绝对值:

>>> v = Vector(3, 4)
>>> abs(v)
5.0

__mul__实现了乘法:

>>> v * 3
Vector(9, 12)

__repr__实现了对象的字符串表示:

Vector(4, 5)

否则得到的字符串可能是<Vector object at 0x10e100070>

__bool__实现了布尔值:

if Vector(4, 5):
    return True

其他魔法方法

一篇文章是讲不完魔法方法的,我们会在后续文章中,继续探讨如何使用和实现它们。

Tips

本小节内容是我看《流畅的Python》第一遍时记录的知识点:

小结

本文是Python进阶系列开篇,参考《流畅的Python》序章改写而成。原书内容有深度有广度,我选择了其中的魔法方法知识点,作为切入,循序渐进学习。其实书中这一章节的副标题是“数据模型”,它是个什么概念呢?

系列文章会不定期同步到在线电子书中,欢迎访问查看: https://dongfanger.gitee.io/blog/

参考资料: 《流畅的Python》 https://docs.python.org/3/reference/datamodel.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python元组拆包捡到8倍镜快准狠

    把元组一一对应拆出来,就叫做元组拆包。拆包有个要求,元组中的元素数量必须跟接受这些元素的空挡数一致,否则会报错:

    dongfanger
  • 接口自动化框架pyface详细介绍

    本框架系本人结合一些实践经验和开源框架设计思想,在家基于兴趣爱好独立完成的代码开发。

    dongfanger
  • 【云+社区年度征文】真香,理解记忆法学习Python基础语法

    在写完这篇文章的第一遍后,我发现并没有写出新意,很可能读者看到后,会和我当初一样,很快就忘了。我现在已经不是读者而是作者了,我想我可以做出一些改变,降低阅读门槛...

    dongfanger
  • Pytorch中的数据加载艺术

    数据库DataBase + 数据集DataSet + 采样器Sampler = 加载器Loader

    marsggbo
  • 文章要保存为TXT文件,其中的图片要怎么办?Python帮你解决

    用 python 爬取你喜欢的 CSDN 的原创文章,保存为TXT文件,不仅查看不方便,而且还无法保存文章中的代码和图片。

    松鼠爱吃饼干
  • 交互式python shell之ipyt

    IPython是Python的交互式Shell,提供了代码自动补完,自动缩进,高亮显示,执行Shell命令等非常有用的特性。特别是它的代码补完功能,例如:在输入...

    py3study
  • RabbitMQ详解(一)------简介与安装

    IT可乐
  • Voicera获1450万美元融资,智能语音真的前途无限吗?

    【数据猿导读】美国AI初创公司Voicera推出一款名为Eva的AI助理,能自动把会议录音转换成文字记录。近日公司宣布已获得1450万美元融资 编译 | 金又南...

    数据猿
  • 3389 Windows 远程端口修改工具

    https://pan.baidu.com/s/1Rt3ZFXY0sOD5okeb9VI3_A

    shawyang
  • docker安装rabbitmq

    似水的流年

扫码关注云+社区

领取腾讯云代金券