看流畅的python感觉有难度_《流畅的python》第一天

实现 len 和 []

我们看到 『Python』可以用 len() 或者arr[0],它们是怎么实现的,其实就是两个魔法方法__len__和__getitem__,用扑克牌的例子学习一下,我们知道知道扑克牌有花色(黑桃,红桃,方块,梅花),有大小(2 -10 JQKA),如何创造一套牌的对象呢?

首先学习 collections的 namedtuple,这是一个快速创建对象,有少数属性但是没有方法的,进一步学习可以查相关文档。这个非常适合作我们一张牌的对象。所以创建一套牌对象代码如下:

from collections import namedtuple

Card = 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, item):

return self._cards[item]

上面是一套牌对象,有魔法方法__len__,__getitem__

我们测试一下代码

if __name__ == '__main__':

import random

deck = FrenchDeck()

# 求长度

print("长度", len(deck))

# 索引

print("索引0", deck[0])

print("索引-1", deck[-1])

# 切片

print("切片", deck[1:4:2])

# 迭代

for card in deck:

print("迭代", card)

# 包含

print("包含", Card("Q", "hearts") in deck)

# 随机选择

print("随机选择", random.choice(deck))

# 排序 我们认为数字2最小 A最大 花色 黑桃>红桃>方块>梅花

def sort_help(card):

suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)

rank_val = deck.ranks.index(card.rank)

return rank_val * 4 + suit_values[card.suit]

for card in sorted(deck, key=sort_help):

print("排序", card)

我们可以把对象像数组一样操作,可以求长度,索引,迭代,包含,排序等。。。

模拟数值类型

我们用向量来举例子,要实现一下需求向量加法 Vector(2, 4) + Vector(2, 1) = Vector(4, 6)

向量乘法Vector(3, 4) * 3 = Vector(9, 12)

向量的模 |Vector(3, 4)| = 5

上面Vector类的实现要用到 __repr__, __abs__, __add__, __mul__代码如下

from math import hypot

class Vector:

def __init__(self, x: int = 0, y: int = 0):

self.x = x

self.y = y

def __repr__(self):

return "Vector({}, {})".format(self.x, self.y)

# 求模

def __abs__(self) -> float:

return hypot(self.x, self.y)

# 求bool

def __bool__(self) -> bool:

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, other):

return Vector(self.x * other, self.y * other)我们

我们测试代码

if __name__ == '__main__':

x1 = Vector(3, 4)

x2 = Vector(6, 8)

# __repr__ 和 __str__ 的区别

# __str__ 只有 str 或者 print被使用

# 如果只想实现一个 __repr__是更好的选择,因为如果一个对象

# 没有 __str__ 函数,而 Python 又需要调用它的时候,解释器会用 __repr__ 作为替代。

print(x1)

# 求模

print(abs(x1))

# 加

print(x1 + x2)

# 乘

print(x1 * 3)

# bool

print(bool(x1))

附上特殊方法一览表:跟运算符无关的特殊方法

运算符相关的

小结:我们自定义数据可以表现和内置类型一样,通过魔法方法实现。

__repr__方便我们调试和记录日志,__str__来给终端用户看。

记录学习 《流畅的python》第一天,一定要坚持下去!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值