魔术方法
特殊方法 的昵称,特其名字以两个下划线开头,以两个下划线结尾(例如 __getitem__
)在类中重写魔术方法,实际上是在类中对python的内置方法进行重载.
e.g., 为了能求得my_collection[key]
的值,解释器实际上会调用my_collection.__getitem__(key)
. 如果在某个类中,重写了__getitem__
方法,那么下次再使用my_collection[key]
时调用的将会是重写过的方法.
1.1 一摞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]
Save as ./cards_1_1.py
>>> from cards_1_1 import FrenchDeck
>>> deck = FrenchDeck() # 创建一个FrenchDeck类的实例
>>> len(deck) # 重写len方法,调用重写后的方法
52
NOTE 1:
- 在使用len(deck)时,事实上是调用了
deck.__len__()
.而__len__是绑定方法,因此可以自动传入self参数- 在代码中,
__len__
方法返回的是len(self._cards)
,- 在 FrenchDeck 类中,
self._cards
是一个列表,是python内置的数据类型len(list)
返回的是列表长度,因此对 FrenchDeck 类使用len()
操作如同对列表使用一样
>>> deck[0] # 取第一个元素
Card(rank='2', suit='spades')
>>> deck[-1] # 取最后一个元素
Card(rank='A', suit='hearts')
NOTE 2:
- 实际上是通过
__getitem__
的方式- 通过
__getitem__
方法,对 FrenchDeck 类使用 [ ] 操作相当于对一个列表使用 [ ] 操作。当且仅当你使用[]操作时,FrenchDeck 类的实例可以看作一个列表,所有基于列表 [ ] 的方法都可以应用在该类上__getitem__
方法把 [ ] 操作交给了self._cards
列表,所以 deck 类自动支持切片(slicing)操作__getitem__
方法同时也将对象变成可迭代的。可以使用for...in...
,它会按顺序做一次迭代的搜索
>>> from random import choice
>>> card = choice(deck)
>>> card
Card(rank='8', suit='hearts')
NOTE 3:
用 python 内置的 random 模块,其中的 random.choice() 方法来随机取一个元素
note_1: str.split( )
以空格为分隔符,包含\n
, 返回分割后的字符串列表.
note_2: namedtuple 是collections 模块中定义的数据类型. Python拥有一些内置的数据类型(str,int,list,tuple,dict, etc),而collections模块在这些内置数据类型的基础上,提供了额外的数据类型.
collections.namedtuple
- namedtuple 是继承自 tuple 的子类,namedtuple 创建一个和 tuple 类似的对象
- 该对象拥有自己的名称. 它更像是一个带有多个数据属性的类,不过里面的数据是只读的.
- 用namedtuple可以很方便的定义一种数据类型,它具备tuple的不变性,又可以根据属性来引用.
Taking nameetuple for example:
from collections import namedtuple
Tpoint=namedtuple("Tpoint",["x","y"])
p=Tpoint(x=10,y=20)
print(p.x)
# 10
print(p.y)
# 20
print(p[0])
# 10
print(p[1])
# 20
# 把数据变成namedtuple类:_make
t=[11,21]
p=Tpoint._make(t)
print(p)
# Tpoint(x=11, y=21)
# 将字典变为namedtuple
dic={"x":30,"y":40}
dic_tuple=Tpoint(**dic)
print(dic_tuple)
# Tpoint(x=30, y=40)