牛,这才是设计!一个小例子学习元组的进阶应用

作者:麦叔

来源:麦叔编程


设计选择

一个类一般应该有数据和行为。数据是属性,行为是方法。

但当一个类只有数据的时候,我们就有了很多其他的选择。

假设我们要存储股票信息Stock。我们至少有两个选择:

  • 创建一个普通的类
  • 使用元组

创建类略有繁琐,感觉必要性不大。而且普通类的性能,不如元组快。

元组的缺点

使用元组也很方便,比如:

stock1 = ('苹果', 100, 80, 88) 
stock2 = ('百度', 80, 63, 65) 

# 打印最高价格
print(stock2[1])

# 打印最低价格
print(stock2[2])

# 打印收盘价格
print(stock2[3])

输出结果:

80
63
65
[Finished in 100ms]

读一下上面的代码,你会立刻感觉到元组虽然快捷,但是也有很致命的缺点:

可读性太差!stock1[1], stock[2],stock[3]等都是魔术数字,不知道什么意思!

而且:

一不小心就可能用错。

下面就请出本文的主角:NamedTuple。

使用NamedTuple

NamedTuple就是为了解决上面的问题而存在的。

直接看例子,看看NamedTuple如何解决上面的尴尬:

from typing import NamedTuple
class Stock(NamedTuple):
    name: str
    high: float
    low: float
    end: float

stock1 = Stock('苹果', 100, 80, 88)
stock2 = Stock(name='百度', high=80, low=63, end=65)

print(stock2.high)
print(stock2.low)
print(stock2.end)

输出结果:

80
63
65
[Finished in 36ms]

为了解决上面的问题,我们可以

  1. 继承NamedTuple,定义一个Stock类
  2. 在类中给元组中存放的每个元素取名字

这样我们就可以通过名字访问它们了,不用担心魔术数字。

你看上面的打印语句根本不用添加注释了。因为「最好的注释就是一看就懂的代码」

你可能会说:这不还是定义了一个类吗?和定义类有什么区别?

它有这么几个优点:

  1. 它比普通要更简洁。不用写__init__等方法。
  2. 也不用写用于打印的__repr__方法,可以直接打印出易懂的数据。
  3. 更重要的是它具有元组所有的优点和用法,因为它就是个元组。

看看下面的例子:

print(stock1)

print("打印最高价----")
print(stock1[1])


print("循环访问元素----")
for item in stock1:
 print(item)

输出结果:

Stock(name='苹果', high=100, low=80, end=88)
打印最高价----
100
循环访问元素----
苹果
100
80
88
[Finished in 41ms]

如上所示:

  • 我们可以打印出对人类友好的对象
  • 我们可以使用下标访问元素,但这不推荐
  • 我们可以使用for循环访问元素,因为它仍然是元组

结论

说说最后的结论:

  • 「千万不要」像本文第1个例子那样使用元组,否则我代表其他麦友鄙视你。
  • 使用普通的对象也可以,但如果你的类不需要行为,也不需要修改,使用NamedTuple是个更好的选择。

元组是不可变的,那如果我的数据的值可能会改变,应该怎么办呢?

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章