第一章


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 进行一次排序,现在需要根据从 2A并且按照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)

python 初始化多个list python list method_python 初始化多个list