第一章
Python 数据模型
Python 特殊句法:名字以两个下划线开头和两个下划线结尾(eg. __getitem__),这些特殊的方法名能够让我们自己的对象实现以下的语言构架:
- 迭代
- 集合类
- 属性访问
- 运算符重载
- 函数和方法的调用
- 对象的创建和销毁
- 字符串表示形式和格式化
- 管理上下文(with 块)
magic method(== dunder method)
1.1 实现 __getitem__ and __len__
补充collctions.namedtuple()
用于构建少数属性但是没有方法的对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imuy7cKG-1621347172771)(C:\Users\65921\AppData\Roaming\Typora\typora-user-images\image-20210517234104051.png)]
"""
定义命名元组
"""
import collections
Card = collections.namedtuple('Cards', ['rank', 'suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'sqades diamondes clulbs 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]
if __name__ == '__main__':
Bicycle = FrenchDeck()
print(len(Bicycle))
print('-'*25)
print(Bicycle[3]) # 把操作交给了self._cards 自动支持切片(slicing)操作
print('-'*25)
from random import choice
choice(Bicycle) # 随机抽取 非常方便
特殊方法好处:不用记住怎么得到元素的总数;不用重新定义迭代方法
"""
仅仅一个特殊方法 __getitem__(self):
Bicycle[:3]
Bicycle[12::13]
for i in reversed(Bicycle)
Card('Q', 'hearts') in Bicycle # 隐式迭代
都可以实现
"""
扑克排序
suit_values = dict(sqades=3, heaerts=2, diamonds=1, clubs=0)
def spades_high(card):
rank_value = FrenchDeck.rank.index(card.rank)
return rank_value * len(suit_values) + suit_values[card.suit]
for card in sorted(deck, key=spades_high):
print(card)
代码分析:
由于原本的FrenchDeck类初始化是 如此的
self._cards = [Card(rank, suit) for suit in self.suits # 4个图标
for rank in self.ranks] # 建立卡牌列表 [0, 12] 对应2到A
他是先根据 suit
进行一次排序,现在需要根据从 2
到A
并且按照suaiit
排序,就要进行计算权重排序。首先把所有牌传进函数中,然后进行获取index
,每号牌会有4张不同图标,这里乘4的原因是以免2号牌的黑桃(0+3)权重大于3号的方块权重(1+0),而乘4就能保证号数大的权重一定大于前者(0*4+3 < 1*4+0).
然后把每张牌的权重输入给key,key进行每张权重的大小进行排列。
1.2 使用特殊方法
# 特殊方法是给解释器使用的
# 没有 Bicycle.__len__()的这种写法
len(Bicycle) # 这才对,pyhton自动调用__len__方法
- 通过内置函数 (len, iter, str) 来使用特殊方法是最好的选择,速度更快
- 不要随意添加特殊方法,有些虽然没有被Python内部使用,但以后可能会被使用
模拟数值类型
算数运算符
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):
return hypot(self.x, self.y)
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)
if __name__ == '__main__':
v = Vector(2, 4)
vv = Vector(1, 8)
print(v, vv)
print(v+vv)