python特殊方法(魔法方法)

写过python项目的同学一定非常熟悉__init__这个函数,我们经常在类中实现这个方法来初始化其成员变量,乍一看起来有点像java中的构造函数。实际上__new__才是一个类的构造函数,并且__new__方法都是在__init__之前执行,__new__返回的当前类的实例self是__init__的入参。

在python中,像__new__、__init__这样两边都有双下划线的方法,叫做魔法方法或者特殊方法,也叫双下方法(dunder method)。特殊方法在Python的语言设计中扮演着举足轻重的角色,是Python程序员进阶绕不开的知识点。Python语言参考手册中的"Data Model"(https://docs.python.org/3/reference/datamodel.html)一章中列出了83个特殊方法的名字,其中47个用于实现算数运算、位运算和比较操作。今天我们就来看下涉及到特殊方法常见的几个场景。

一、make custom types pythonic

在我们自定义的类中,我们去实现特定的双下方法,就可以使用相应的内置函数来操作我们的自定义类。

举个例子:

使用namedtuple定义一个纸牌类Card,rank代表大小,suit代表花色。

自定义FrenchDeck代表一副牌,保护变量(python中保护变量用单下划线开头)_cards代表13种大小和四种花色所组合成的52张不同的牌(这里不包含大小王)

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])         #具名元组

class FrenchDeck:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')       #range左闭右开
    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]

 首先新建一个FrenchDeck的实例(生成了一副牌):deck = FrenchDeck()

这时我们就可以用len(deck)返回一副牌的数量,因为len方法会调用类的__len__方法;我们可以用deck[0]、deck[1]直接获取一张牌,因为这实际调用的是__getitem__;更高级的,我们还可以对deck进行切片,对deck进行for循环迭代,这都得益于__getitem__。

二、operator overloading

常见算数运算符和对应特殊方法一览表:

+                  __add__

-                   __sub__

*                   __mul__

/                   __truedive__

//                  __floordive__

%                 __mod__

**                 __pod__

 

posted @ 2022-08-24 16:44  方山客  阅读(167)  评论(0编辑  收藏  举报