概述
namedtuple是一个非常有趣(也被低估了)的数据结构。我们可以轻松找到严重依赖常规元组和字典来存储数据的Python代码。我并不是说,这样不好,只是有时候他们常常被滥用,且听我慢慢道来。
假设你有一个将字符串转换为颜色的函数。颜色必须在4维空间RGBA中表示。
def convert_string_to_color(desc: str, alpha: float = 0.0):
if desc == "green":
return 50, 205, 50, alpha
elif desc == "blue":
return 0, 0, 255, alpha
else:
return 0, 0, 0, alpha
复制代码
然后,我们可以像这样使用它:
r, g, b, a = convert_string_to_color(desc="blue", alpha=1.0)
复制代码
好的,可以。但是我们这里有几个问题。第一个是,无法确保返回值的顺序。也就是说,没有什么可以阻止其他开发者这样调用
convert_string_to_color:
g, b, r, a = convert_string_to_color(desc="blue", alpha=1.0)
复制代码
另外,我们可能不知道该函数返回4个值,可能会这样调用该函数:
r, g, b = convert_string_to_color(desc="blue", alpha=1.0)
复制代码
于是,因为返回值不够,抛出ValueError错误,调用失败。
确实如此。但是,你可能会问,为什么不使用字典呢?
Python的字典是一种非常通用的数据结构。它们是一种存储多个值的简便方法。但是,字典并非没有缺点。由于其灵活性,字典很容易被滥用。让 我们看看使用字典之后的例子。
def convert_string_to_color(desc: str, alpha: float = 0.0):
if desc == "green":
return {"r": 50, "g": 205, "b": 50, "alpha": alpha}
elif desc == "blue":
return {"r": 0, "g": 0, "b": 255, "alpha": alpha}
else:
return {"r": 0, "g": 0, "b": 0, "alpha": alpha}
复制代码
好的,我们现在可以像这样使用它,期望只返回一个值:
color = convert_string_to_color(desc="blue", alpha=1.0)
复制代码
无需记住顺序,但它至少有两个缺点。第一个是我们必须跟踪密钥的名称。如果我们将其更改{"r": 0, “g”: 0, “b”: 0, “alpha”: alpha}为{”red": 0, “green”: 0, “blue”: 0, “a”: alpha},则在访问字段时会得到KeyError返回,因为键r,g,b和alpha不再存在。
字典的第二个问题是它们不可散列。这意味着我们无法将它们存储在set或其他字典中。假设我们要跟踪特定图像有多少种颜色。如果我们使用collections.Counter计数,我们将得到TypeError: unhashable type: ‘dict’。
而且,字典是可变的,因此我们可以根据需要添加任意数量的新键。相信我,这是一些很难发现的令人讨厌的错误点。
好的,很好。那么现在怎么办?我可以用什么代替呢?
namedtuple!对,就是它!
将我们的函数转换为使用namedtuple:
from collections import namedtuple
...
Color = namedtuple("Color", "r g b alpha")
...
def convert_string_to_color(desc: str, alpha: float = 0.0):
if desc == "green":
return Color(r=50, g=205, b=50, alpha=alpha)
elif desc == "blue":
return Color(r=50, g=0, b=255, alpha=alpha)
else:
return Color(r=50, g=0, b=0, alpha=alpha)
复制代码
与dict的情况一样,我们可以将值分配给单个变量并根据需要使用。无需记住顺序。而且,如果你使用的是诸如PyCharm和VSCode之类的IDE ,还可以自动提示补全。
color = convert_string_to_color(desc="blue", alpha=1.0)
...
has_alpha = color.alpha > 0.0
...
is_black = color.r == 0 and color.g == 0 and color.b == 0
复制代码
最重要的是namedtuple是不可变的。如果团队中的另一位开发人员认为在运行时添加新字段是个好主意,则该程序将报错。
>>> blue = Color(r=0, g=0, b=255, alpha=1.0)
>>> blue.e = 0
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-13-8c7f9b29c633> in <module>
----> 1 blue.e = 0
AttributeError: 'Color' object has no attribute 'e'
复制代码
不仅如此,现在我们可以使用它Counter来跟踪一个集合有多少种颜色。
>>> Counter([blue, blue])
>>> Counter({Color(r=0, g=0, b=255, alpha=1.0): 2})
复制代码
最后
以上就是奋斗早晨为你收集整理的为什么要使用namedtuple?的全部内容,希望文章能够帮你解决为什么要使用namedtuple?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复