一摞有序的卡牌:双下方法(又称魔术方法、特殊方法)的使用
①👇首先构建一个卡牌堆类,使用collections模块中的namedtuple可以直接构建一个简单的卡牌类,但FrenchDeck给出的类定义中重写了该类的魔术方法,通过实现了__len__
使FrenchDeck类对象可以直接通过len()
方法查看纸牌堆中纸牌的数量。通过实现__getitem__
使FrenchDeck类对象可以通过索引和切片对列表进行操作。
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA') #将2→10和J、Q、K、A加入到ranks中
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]
②👇尝试不同的方法。
Ⅰ首先用Card构建一张纸牌。
beer_card = Card('7', 'diamonds')
beer_card
Ⅱ构造一个FrenchDeck有序卡牌类:
deck = FrenchDeck()
len(deck) #FrenchDeck类短小而精悍,可使用len来查看类对象的长度:输出为52,显然因为有52张卡牌。
输出为52,因为不同花色的卡牌共有52张。
Ⅲ尝试用不同的方法取牌。
👆random模块中的choice方法实现了“取列表中随机索引位置的对象”。
Ⅳ反序取卡牌
for card in reversed(deck): #使用reversed方法反向取牌
print(card)
Ⅴ同样,可以通过in
来查看某张卡牌是否在卡牌堆(类对象)中。
实现一个简单的二维向量类:通过双下方法实现运算符重载
👇类定义:
from math import hypot
class Vector:
def __init__(self,x=0,y=0):
self.x = x
self.y = y
def __repr__(self):
return 'Vector {},{}'.format(self.x,self.y)
def __abs__(self):
return hypot(self.x, self.y) #hypot返回的是两个数的欧几里得范式
def __bool__(self):
return bool(abs(self)) #如果向量的模为0,则返回False,否则返回True
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Vector(x, y)
def __mul__(self, scaler): #向量的数乘
return Vector(self.x*scaler, self.y*scaler)
Zen of python
通过执行import this
可以输出python之禅。
len
之所以不是普通方法,是可以让python自定义的数据结构可以走后门,abs
方法也是同理。这个思想印证了python之禅中“实用大于纯粹”的理念。(如果len是内置方法,那么CPython可以直接调用C结构体读取对象的长度,但是让特殊特例破坏既定规则显然不符合the Zen of Python)