1、python一致性
python的优雅之处就在于他的一致性。一致性是指他的背后的设计思想遵循同一种风格,当你掌握这种风格之后,就可以用一种固定的方法操作他们。举个例子,你可以把自定义的类写得像是python内置的list类型,支持list的各种操作。
这种一致性通过实现python的特殊方法实现,也称魔术方法,fluent python作者更愿意称之为特殊方法,因为这是有迹可循的,只是效果magic。
下述例子,在自定义类实现了特殊方法__getitem__(),使对象变成可迭代。
in运算符由于没有实现__contains__()方法,因此使用顺序迭代搜索来对比。
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 rank in self.ranks
for suit in self.suits]
def __len__(self): #对len(obj)函数的支持
return len(self._cards)
def __getitem__(self, index): #实现该方法使对象变得可迭代类型
return self._cards[index]
deck = FrenchDeck()
beer_card = Card(rank='7', suit='diamonds')
print(card in deck) #判断是否存包含
print(len(deck)) #用len(obj)返回长度
for card in deck: #支持迭代
print(card)
#结果输出
True
52
Card(rank='2', suit='spades')
Card(rank='2', suit='diamonds')
...
Card(rank='A', suit='hearts')
还可以实现__add__(),__abs__()等特殊函数,让对象支持加法运算符和abs()函数等等。
2、__repr__()与__str__()
总的来说,两个都是用来将数据转换成字符串输出的。
python中有个内置函数repr,背后就是使用__repr__()。
两者的区别是,__str__()是对print(),str()的支持偏向于输出显示,__repr__()用于支持%r和str.format作为对象的字符化的方法。如果对象没有实现__str__(),相关函数将会调用__repr__()作为替代。因此如果只实现一个应该倾向于__repr__()。
class FrenchDeck:
def __repr__(self):
return 'repr FrenchDeck'
def __str__(self):
return 'str FrenchDeck'
deck = FrenchDeck()
print(deck) #调用str()
#调用repr
print('print1 deck type {!r}'.format(deck))
print('print1 deck type %r' % deck)
#输出结果
str FrenchDeck
print1 deck type repr FrenchDeck
print1 deck type repr FrenchDeck
参考:Fluent Python,主要代码同样摘自此书