专栏首页AI研习社一文了解 Python 的 “Magic” 方法

一文了解 Python 的 “Magic” 方法

本文为 AI 研习社编译的技术博客,原标题 : Python magic methods or special methods 翻译 | 邓普斯•杰弗 校对 | 酱番梨 整理 | 菠萝妹

在以前的文章中,我聊过了Python的 __getitem__ 和 __setitem__ 方法。这些方法被称为“魔法”方法、特殊方法或者dunger方法(译者:国内书籍用“魔法”一词较多)。那么,什么是魔法方法呢?这正是今天我们要说的内容。

P.S.你会再一次的深深的爱上Python语言。

也将是一篇较长的文章,来让我们开始。

魔法方法究竟是什么?

魔法方法是一种具有特殊魅力的正常方法。Python通过这些魔法方法可以赋予你的class魔力。这些魔法方法都是以双下划线(__)作为前缀和后缀。坦率的讲,其实这些方法并没有什么魔法,另外这些方法这Python的文档中也没有较为详细的介绍,因此,今天我们就来详细的看一看这些方法。

魔法方法之初始化

所有的Python开发者都知道,__init__()是一个类(class)的第一个方法,也可以叫做构造函数。虽然,__init__()方法是第一个被创建的,但是它却不是第一个被调用的执行的,__new__()方法才是最早被调用的方法。

  • __new__()方法:先读取参数,如:类名称,args,和kwargs。然后,__new__()方法把这些参数传递给对类名称的__init__()方法。 语法:__new__(class_name, args, kwargs)
  • __init__()方法:是类的初始化方法或构造方法,这也几乎用于全局的初始化目的。 语法:__init__(self, args, kwargs)
  • __del__()方法:类的析构函数。切记,这并不是定义del x,而是定义了一个对象被垃圾回收的行为。 语法:__del__(self)

看一个例子:

class SimpleInit(object):
    '''
        Class to initialize a list with a value
    '''
    def __init__(self, value=10):
        self._list = [value]

    def __del__(self):
        del self._list

魔法方法之算术运算

算术运算是非常常见的,因此,如果你想创建属于自己的数据结构,魔法方法会使你的实现更容易。例如:我们可以像这样,some_list + some_list2,实现Python的列表(list)拼接。类似这种的有趣行为,我们可以通过魔法方法的算术运算实现定义。

  • __add__(self, other) 定义加法 (+)
  • __sub__(self, other) 定义减法 (-)
  • __mul__(self, other) 定义乘法 (*)
  • __floordiv__(self, other) 定义整除法 (//)
  • __div__(self, other) 定义浮点型除法 (/)
  • __mod__(self, other) 定义取余模运算 (%)
  • __and__(self, other) 定义按位与 (&)
  • __or__(self, other) 定义按位或 (|)
  • __xor__(self, other) 定义按位异或 (^)
  • __pow__(self, other) 定义指数运算 (**)
  • __lshift__(self, other) 定义按位左移 (<<)
  • __rshift__(self, other) 定义按位右移 (>>)

例如:

class SimpleAdder(object):
    def __init__(self, elements=[]):
        self._list = elements
        
    def __add__(self, other):
        return self._list + other._list
    
    def __str__(self):
        return str(self._list)
    a = SimpleAdder(elements=[1,2,3,4])b = SimpleAdder(elements=[2, 3, 4])print(a + b)    # [1, 2, 3, 4, 2, 3, 4]

魔法方法之增量赋值

Python不仅允许我们定义算术运算,也允许我们定义增量赋值运算。如果你不知道什么是增量赋值是什么?那么我们来看一个简单的例子:

x = 5
    x += 1              # This first adds 5 and 1 and then assigns it back to 'x'

因此有的时候,你可能想写一些自自定义逻辑实现增量赋值操作。魔法方法支持的运算符有:

  • __iadd__(self, other) 定义加法 (+=)
  • __isub__(self, other) 定义减法 (-=)
  • __imul__(self, other) 定义乘法 (*=)
  • __ifloordiv__(self, other) 定义整除法 (//=)
  • __idiv__(self, other) 定义浮点型除法 (/=)
  • __imod__(self, other) 定义取模运算 (%=)
  • __iand__(self, other) 定义按位与 (&=)
  • __ior__(self, other) 定义按位或 (|=)
  • __ixor__(self, other) 定义按位异或(^=)
  • __ipow__(self, other) 定义指数运算 (**=)
  • __ilshift__(self, other) 定义按位左移 (<<=)
  • __irshift__(self, other) 定义按位右移 (>>=)

魔法方法之比较运算

Python有一组广泛的魔术方法实现比较。我们可以覆盖默认的比较行为,来定义使用对象的引用方法。下面是比较魔法方法的列表:

  • __eq__(self, other) 帮助检查两个对象的相等。它定义了相等运算 (==)
  • __ne__(self, other) 定义了不等运算 (!=)
  • __lt__(self, other) 定义了小于运算 (<)
  • __gt__(self, other) 定义了大于运算 (>)
  • __le__(self, other) 定义了小于等于运算 (<=)
  • __ge__(self, other) 定义了大于等于运算 (>=)

例如:

class WordCounter(object):
    '''
        Simple class to count number of words in a sentence
    '''
    def __init__(self, sentence):
        # split the sentence on ' '
        if type(sentence) != str:
            raise TypeError('The sentence should be of type str and not {}'.format(type(sentence)))
        self.sentence = sentence.split(' ')
        self.count    = len(self.sentence)
        
    def __eq__(self, other_class_name):
        '''
            Check the equality w.r.t length of the list with other class
        '''
        return self.count == other_class_name.count
    
    def __lt__(self, other_class_name):
        '''
            Check the less-than w.r.t length of the list with other class
        '''
        return self.count < other_class_name.count
    
    def __gt__(self, other_class_name):
        '''
            Check the greater-than w.r.t length of the list with other class
        '''
        return self.count > other_class_name.count
    word = WordCounter('Omkar Pathak')print(word.count)

魔法方法之类型转换

很多时候开发人员需要隐性的转换变量类型,来满足最要想要的结果。Python是关心你内在数据的类型的一种动态类型语言,除此之外,Python也关心你,哈哈!如果你想要自定义属于自己的方法,可以借助如下方法:

  • __int__(self) 定义类型转化为 int
  • __long__(self) 定义类型转化为 long
  • __float__(self) 定义类型转化为 float
  • __complex__(self) 定义类型转化为 complex(复数)
  • __oct__(self) 定义类型转化为 octal(八进制)
  • __hex__(self) 定义类型转化为 (十六进制)
  • __index__(self) 定义类型转化为一种int, 当对象被用于切片表达式( a slice expression)时

最常用的魔法方法

这里有一些魔法方法你应该经常遇到:

  • __str__(self) 定义了str()行为。例如,当你调用print(object_name),无论object_name是什么都会被__str__()执行
  • __repr__(self) 定义了repr()行为。这个很大程度上类似于__str__()。这两个之间的主要区别是,str()主要是人类可读的和repr()是机器可读的
  • __hash__(self) 定义了行为调用hash()
  • __len__(self) 返回容器的长度
  • __getitem__(self) 和 __setitem__(self). 更多内容可以详见我以前的博客文章。
  • __delitem__(self, key) 定义了一个删除一个项目的行为. 例如, del _list[3]
  • __iter__(self) 返回一个迭代容器
class CustomList(object):
    def __init__(self, elements=0):
        self.my_custom_list = [0] * elements

    def __str__(self):
        return str(self.my_custom_list)

    def __setitem__(self, index, value):
        self.my_custom_list[index] = value

    def __getitem__(self, index):
        return "Hey you are accessing {} element whose value is: {}".format(index, self.my_custom_list[index])

    def __iter__(self):
        return iter(self.my_custom_list)obj = CustomList(12)obj[0] = 1print(obj[0])print(obj)

把这些有魔法的Python礼物送给你,除此之外,还有更多类似的方法,在你需要的时候可以仔细研究。在我研究魔法方法的时候,遇到了一个类似的博客,我强烈建议你去读一下该文章。

如果有人知道更多的方法请在评论中说明,或者如果你想共享的话,可以直接打开超链接。:)

coding 快乐!

本文分享自微信公众号 - AI研习社(okweiwu)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-07

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 支招 | 使用Pytorch进行文本分类

    dropout的值要在 0.1 以下(经验之谈,笔者在实践中发现,dropout取0.1时比dropout取0.3时在测试集准确率能提高0.5%)。

    AI研习社
  • GPT-2没什么神奇的,PyTorch 就可以复现代码

    我读过的最精彩、解释最清楚的文章之一是「The Annotated Transformer」https://nlp.seas.harvard.edu/2018/...

    AI研习社
  • 使用以 Tensorflow 为后端的 Keras 构建生成对抗网络的代码示例

    生成式对抗网络(GAN)是近期深度学习领域中最有前景的发展之一。 GAN由Ian Goodfellow于2014年推出,它通过分别训练两个相互竞争和合作的深度网...

    AI研习社
  • 一文了解 Python 的 “Magic” 方法

    原标题 :Python magic methods or special methods

    崔庆才
  • TensorFlow强化学习入门(4)——深度Q网络(DQN)及其扩展

    本文中我们将一起创建一个深度Q网络(DQN)。它基于我们系列文章中(0)的单层Q网络,如果你是强化学习的初学者,我推荐你到文末跳转到(0)开始阅读。尽管简单的Q...

    ArrayZoneYour
  • 小蛇学python(2)两百行代码实现旅游中国34座大城市最短路径

    直接说基础语法,也许大家不会感兴趣。前言之后的这一章,给大家介绍一下我最近写出来的一个小功能。用python语言实现GA算法来解决TSP问题,希望以此来激发大家...

    用户2145057
  • 堆排序和优先队列的核心,堆究竟是怎样的数据结构?

    和链表、二叉树以及数组这些热门的数据结构相比,堆相对比较冷门。如果你对数据结构了解不深的话,可能很少听说。但是我们经常用到它,虽然可能你并不一定能感知到。比如说...

    TechFlow-承志
  • ReactiveCocoa,最受欢迎的iOS函数响应式编程库(2.5版),没有之一!

    简介 项目主页: ReactiveCocoa 实例下载: https://github.com/ios122/ios122 简评: 最受欢迎,最有价值的iOS响...

    ios122
  • 11 Python 基础: 知识巩固,实现一个简易学生管理系统

    首先,我们定义了一个LoginModule类,此为登录模块,主要功能就是定义账号属性【用户名,密码】,然后定义一个登录login方法实现验证用户名和密码是否正确...

    小Gy
  • PyQt 5信号与槽的几种高级玩法

    在Qt中,每一个QObject对象和PyQt中所有继承自QWidget的控件(这些都是QObject的子对象)都支持信号与槽机制。当信号发射时,连接的槽函数将会...

    博文视点Broadview

扫码关注云+社区

领取腾讯云代金券