通过实现一些特定的方法,会赋予类一些特定的功能,
- 一摞Python风格的纸牌
import collections
from random import choice
Card = collections.namedtuple('Card',['rank','suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suits = '黑桃 方片 梅花 红桃'.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, prosition):
return self._cards[prosition]
card = FrenchDeck()
说明:
- nametuple:具名元祖,可以用来快速生成一个简单的对象
- __len__方法:python内置魔法方法,实现了__len__方法的对象,支持内置函数len(),注意:python内置的对象使用len()速度会很快,CPython 会直接从一个 C 结构体里读取对象的长度,完全不会调用任何方法。
如果是自己实现的len方法,那么python会调用__len__方法。 - __getitem__方法:实现了getitem方法的对象都是可以被迭代的,甚至可以被切片。
关于特殊方法:
- 特殊方法大多情况下是隐式调用的,比如for i in x:这个语句,背后其实调用的是iter(x)方法,iter(x)背后又调用了x.iter,前提是这个方法在x中已经实现了。
- 特殊方法的存在是为了被 Python 解释器调用的,开发者并不需要调用它们。
- 如何使用特殊方法
# 一个向量类,虽然实现了很多方法,但是并不会在这个类的自身代码中使用,而是提供给解释器调用的
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__和__mul__ 实现+和*,
# bool值
python的任何对象都可以用于需要布尔值的上下文中
为了判断一个值是真是假,python会调用bool(x)
默认情况下,我们自己定义的类的实例总是被认为是真的,除非这个类对__bool__或者__len__有自己的实现。
bool(x)会调用x.__bool__(),如果不存在__bool__方法,则会调用x.__len__,len返回0则是假。
# 关于bool 和 or
一种高效的写法
def __bool__(self):
return bool(self.x or self.y)
or运算符会返回x或者y本身的值:若x的值等价于真,则or返回x的值否则返回y的值
特殊方法一览;
总结:
- 一个类实现了__getitem__ 那么这个类的对象就可以使用切片,遍历,可以对其使用in方法,如果类没有实现__contains__方法,那么in方法按照顺序做一次迭代操作。(而迭代操作使用到__getitem__方法)。
- 如果一个类实现了一些特定的双下划线方法,那么他可以用于一些python内置的方法。比如,通过实现__len__和__gititem__方法,那么这个类就和python自有的序列类型一样,可以用于标准库的random.choice, reversed ,sorted等方法。