什么是 Python Data Model?
Python Data Model 为自定义的数据类型(通过 Class)提供与 Python 内建类型一致的接口。
实现方法是:在类中定义一些特殊的方法,比如 __add__()
;当开发者调用 len(object)
时,python 解析器将执行 object.__len__()
作用:使所有 Python 对象拥有一致的接口。
实现:通过特殊的语法 调用 对象中的特殊方法
例子:object[key]
--> object.__getitem__(key)
__getitem__
, __len__
目标:实现类的 __getitem__()
和 __len__()
方法
Python 特性补充
collections.namedtuple:可用于创建没有方法的对象
>>> import collections
# 坐标轴上的一点
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p1 = Point(5, 10)
>>> p2 = Point(x=50, y=100)
>>> repr(p1)
'Point(x=5, y=10)'
# 访问元组中的项
# 通过项名
>>> p1.x
5
>>> p1.y
10
# 通过索引
>>> p1[0]
5
>>> p1[1]
10
# 解包
>>> x, y = p1
>>> x
5
>>> y
10
>>> p1
Point(x=5, y=10)
namedtuple
# 根据字符串创建列表
>>> list("ABC")
['A', 'B', 'C']
>>> 'A B C'.split()
['A', 'B', 'C']
# 列表相加
>>> [1, 2, 3]+list("ABC")
[1, 2, 3, 'A', 'B', 'C']
例子:扑克牌
import collections
class FrenchDeck:
'''一副扑克牌'''
# 一张扑克牌
# rank: 号码
# suit: 花色
Card = collections.namedtuple('Card', ['suit', 'rank'])
suits = 'spades diamonds clubs hearts'.split()
ranks = [i for i in range(2, 11)] + list('JQKA')
def __init__(self):
self._card = [self.Card(suit, rank) for suit in self.suits
for rank in self.ranks]
def __len__(self):
'''卡牌的数量(数组的长度'''
return len(self._card)
def __getitem__(self, positon):
'''获取一张卡牌(数组中的一个元素)
* 支持索引
* 支持切分
* 支持迭代
'''
return self._card[positon]
In [1]: import Poker
In [3]: poker = Poker.FrenchDeck()
In [4]: len(poker)
Out[4]: 52
In [5]: poker[1]
Out[5]: Card(suit='spades', rank=3)
In [6]: poker[0]
Out[6]: Card(suit='spades', rank=2)
# 前3张牌
In [11]: poker[:3]
Out[11]:
[Card(suit='spades', rank=2),
Card(suit='spades', rank=3),
Card(suit='spades', rank=4)]
# 随机选取一张扑克牌
In [8]: import random
In [10]: random.choice(poker)
Out[10]: Card(suit='diamonds', rank='Q')
好处
- 拥有和 Python 内建类型一致的 API (
len
) - 获得 Python 特性:切片,迭代
- 获得 Python 标准库支持:
reversed
,sorted
,random.choice
注意
- 自己不要使用
__foo__
的变量名,它们使保留给这些特殊方法/变量使用的 - 除了 直接调用父类的
__init__
方法外,一般不直接调用这些特殊的方法,而是使用len
foo[0]
模拟数值计算
- + :
__add__
- * :
__mul__
- abs():
__abs__
当穿给 __add__
的两个参数的类型不同时,其顺序要符合定义时的顺序;
或者可以使用 __radd__
方法
布尔运算
bool(objct)
返回 True 或 False
当调用 bool()
时:
- python 解析器尝试调用对象的
__bool__
方法 -
__bool__
未定义时,参数调用__len__
方法:0 为 False,其他为 True - 如果
__bool__
和__len__
都为定义,对象将永远被视为 True
字符串带表
-
__repr__
: 用于 debug,代表一个对象。应尽可能地还原构造对象的样子,比如Point(1, 2)
-
__str__
:用于展示给用户看,执行print(object)
时调用此方法;若未实现该方法,会调用__repr__
- 如果只实现一个方法,选择
__repr__
网友评论