python魔术方法是特殊方法的昵称。它是简单而又强大,为了被python解释器调用而存在的方法。python提供丰富的元对象协议,让语言的用户和核心开发者拥有并使用同样的工具
例子引用《流畅的Python》- 一摞python风格的纸牌
import collections
# namedtuple用来构建只有少数属性但是没有方法的对象
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]
__getitem__方法将使自定义类对象有些比较常见、基础的能力:
1.可以通过下标获取值
deck = FrenchDeck()
print(deck[1])
2.可以随机选出一个值
from random import choice
print(deck)
3.可以对实例对象切片
print(deck[:3])
4.可以对实例对象执行遍历操作
备注:__getitem__方法使实例对象变成可迭代对象
for card in deck:
print(card)
for card in reversed(deck):
print(card)
5.可以使用in关键字执行布尔判断
备注:没有实现__contains__方法的集合类型中,in运算符会按顺序做一次迭代搜索
print(Card('Q', 'hearts') in 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): # abs函数返回函数的绝对值
return hypot(self.x, self.y) # hypot返回欧几里德范数,如直角三角形的斜边长
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__
内置对象中,双下repr方法用来返回对象的字符串表现形式,如果没有此方法,我们打印的信息可能只有对象类和内存地址。
__repr__和__str__的区别在于,后者是str()执行时,或是用print()函数打印对象时才被调用,并且的它的返回值对终端用户更友好。如果一个对象没有__str__方法,而python又需要调用它时,解释器会用__repr__作为代替
__add__和__mul__
使向量类实例对象可以使用算术运算符+和*进行运算。并且都是不改变源对象的前提下,计算并返回新对象。遵循中缀运算符的基本原则:不改变操作对象,而是产出一个新的值
__bool__
尽管python里有bool类型,但实际上任何对象都可以用于需要布尔值的上下文中(比如if或while语句,或者and、or和not运算符)。python通过bool()函数来对对象判断真假。解释器默认调用__bool__方法,当此函数未定义时,会尝试调用__len__方法
v1 = Vector(2, 4)
v2 = Vector(2, 1)
print(v1 + v2) # Vector(4, 5)
v = Vector(3, 4)
print(abs(v)) # 5.0
print(v * 3) # Vector(9, 12)
print(abs(v * 3)) # 15.0