整理自 Luciano Ramalho 所著的 《流畅的Python》第一章
Python解释器碰到特殊的句法时,会使用特殊方法去激活一些基本的对象操作,这些特殊方法的名字以两个下划线开头,以两个下划线结尾,如__getitem__。
考虑一下例子,这个例子中用到了__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]
这段代码展示了两个特殊方法的用法(不算__init__)。可以对FrenchDeck对象直接调用len()方法以及[]操作。
>>> deck = FrenchDeck()
>>> len(deck)
52
>>> deck[0]
Card(rank='2', suit='spades')
__getitem__方法把[]操作交给了self._cards列表,因此deck类自动支持切片操作。
再举一个例子,实现另外几种特殊函数。
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)
其中:
- __repr__:把一个对象用字符串的形式表达出来。和__str__的区别在于后者是在str()函数被使用,或者用print函数打印时才被调用。如果一个对象没有__str__函数,解释器会用__repr__作为替代
- __bool__:若果不存在,使用__len__函数代替