Python 风格
Python 最好的品质之一就是一致性。它通过某种方式制定了一系列规范,我们可以使用这些规范去写出最地道的Python风格的代码。而这一套规范具体体现在哪里呢? 答案是Magic Function。
Magic Function(魔术方法)
一撂Python风格的纸牌
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]
FrenchDeck
类实现了3个Magic Function __init__
, __len__
, __getitem__
。这使得我们十分方便得能够使用Python内置的函数。
deck = FrenchDeck()
print len(deck) # 获取deck长度
print deck[0] #获取deck第0个元素
print deck[-1] #获取deck最后一个元素
# 下面是随机抽deck的某个元素
from random import choice
print choice(deck)
### Output: Card(rank='3', suit='hearts')
# 获取deck某一分片的元素
print deck[:3]
# 遍历
for card in deck:
print card
# 反向遍历
for card in reversed(deck):
print card
# 判断一个Card是否在deck中
print Card('Q', 'hearts') in deck
# 排序
suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
def spades_high(card):
rank_value = FrenchDeck.ranks.index(card.rank)
return rank_value * len(suit_values) + suit_values[card.suit]
for card in sorted(deck, key=spades_high):
print card
如何使用Magic Function
- 当我们定义好Magic Function后,并不需要显式的去使用它,而是通过使用Python内置函数,如
len(my_object)
去使用__len__
方法。 - 对于一些内置的类来说,使用内置函数速度更快。因为CPython会抄近路,
__len__
实际会直接返回PyVarObject
里的ob_size
属性。PyVarObject
是表示内存中长度可变的内置对象的C语言结构体。直接读取这个值比调用一个方法快很多。 - 不要想当然的随意添加Magic Function, 比如
__foo__
,虽然现在没有,但以后就不一定了。
其他Magic Function
__repr__
- 输出一个对象的字符串形式。
- 与
__str__
的区别:- 前者为了明确,后者为了可读。
- 后者是在
str()
函数被使用,或者在用print
函数打印一个对象的时候才被调用,并且返回的字符串对终端更友好。 - 如果一个对象没有
__str__
函数,而Python又需要调用它的时候,解释器会用__repr__
作为代替。 - https://stackoverflow.com/questions/1436703/difference-between-str-and-repr
第一章内容简单来说就是介绍Python风格的coding以及magic function的使用。后续我们会深入了解Python自带的数据结构。