Python数据结构:一个被低估的Namedtuple(一)-Python教程

资源魔 26 0
Python教程栏目为各人引见Python数据构造中的Namedtuple。

本文将探讨python中namedtuple的重点用法。咱们将由浅入深的引见namedtuple的各概念。您将理解为何要应用它们,和若何应用它们,从而是代码更简约。正在学习本指南之后,你肯定会喜爱上应用它。

学习指标

正在本教程完结时,您应该可以:

  • 理解为何和什么时候应用它
  • 将惯例元组以及字典转换为Namedtuple
  • Namedtuple转化为字典或惯例元组
  • Namedtuple列表进行排序
  • 理解Namedtuple以及数据类(DataClass)之间的区分
  • 应用可选字段创立Namedtuple
  • Namedtuple序列化为JSON
  • 增加文档字符串(docstring)

为何要应用namedtuple

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 = 0AttributeError: 'Color' object has no attribute 'e'复制代码

不只如斯,如今咱们能够应用它Counter来跟踪一个荟萃有几何种颜色。

>>> Counter([blue, blue])>>> Counter({Color(r=0, g=0, b=255, alpha=1.0): 2})复制代码

若何将惯例元组或字典转换为 namedtuple

如今咱们理解了为何应用namedtuple,如今该学习若何将惯例元组以及字典转换为namedtuple了。假定因为某种缘由,你有蕴含黑白RGBA值的字典实例。假如要将其转换为Color namedtuple,则能够按如下步骤进行:

>>> c = {"r": 50, "g": 205, "b": 50, "alpha": alpha}>>> Color(**c)>>> Color(r=50, g=205, b=50, alpha=0)复制代码

咱们能够行使该**构造将包解紧缩dictnamedtuple

假如我想从dict创立一个namedtupe,若何做?

没成绩,上面这样做就能够了:

>>> c = {"r": 50, "g": 205, "b": 50, "alpha": alpha}>>> Color = namedtuple("Color", c)>>> Color(**c)
Color(r=50, g=205, b=50, alpha=0)复制代码

经过将dict实例通报给namedtuple工场函数,它将为你创立字段。而后,Color像上边的例子同样解压字典c,创立新实例。

若何将 namedtuple 转换为字典或惯例元组

咱们刚刚学习了若何将转换namedtupledict。反过去呢?咱们又若何将其转换为字典实例?

试验证实,namedtuple它带有一种称为的办法._asdict()。因而,转换它就像挪用办法同样简略。

>>> blue = Color(r=0, g=0, b=255, alpha=1.0)>>> blue._asdict()
{'r': 0, 'g': 0, 'b': 255, 'alpha': 1.0}复制代码

您可能想晓得为何该办法以_扫尾。这是与Python的惯例标准纷歧致的一个中央。通常,_代表公有办法或属性。然而,namedtuple为了不定名抵触将它们增加到了公共办法中。除了了_asdict,另有_replace_fields以及_field_defaults。您能够正在这里找到一切这些。

要将namedtupe转换为惯例元组,只要将其通报给tuple结构函数便可。

>>> tuple(Color(r=50, g=205, b=50, alpha=0.1))
(50, 205, 50, 0.1)复制代码

若何对namedtuples列表进行排序

另外一个常见的用例是将多个namedtuple实例存储正在列表中,并依据某些前提对它们进行排序。例如,假定咱们有一个颜色列表,咱们需求按alpha强度对其进行排序。

侥幸的是,Python容许应用十分Python化的形式来执行此操作。咱们能够应用operator.attrgetter运算符。依据文档,attrgetter“前往从其操作数猎取attr的可挪用工具”。简略来讲就是,咱们能够经过该运算符,来猎取通报给sorted函数排序的字段。例:

from operator import attrgetter
...
colors = [
    Color(r=50, g=205, b=50, alpha=0.1),
    Color(r=50, g=205, b=50, alpha=0.5),
    Color(r=50, g=0, b=0, alpha=0.3)
]
...>>> sorted(colors, key=attrgetter("alpha"))
[Color(r=50, g=205, b=50, alpha=0.1),
 Color(r=50, g=0, b=0, alpha=0.3),
 Color(r=50, g=205, b=50, alpha=0.5)]复制代码

如今,颜色列表按alpha强度升序陈列!

若何将namedtuples序列化为JSON

有时你可能需求将贮存namedtuple转为JSON。Python的字典能够经过json模块转换为JSON。那末咱们能够应用_asdict办法将元组转换为字典,而后接上去就以及字典同样了。例如:

>>> blue = Color(r=0, g=0, b=255, alpha=1.0)>>> import json>>> json.dumps(blue._asdict())'{"r": 0, "g": 0, "b": 255, "alpha": 1.0}'复制代码

若何给namedtuple增加docstring

正在Python中,咱们能够应用纯字符串来记载办法,类以及模块。而后,此字符串可作为名为的非凡属性应用__doc__。话虽这么说,咱们若何向咱们的Color namedtuple增加docstring的?

咱们能够经过两种形式做到这一点。第一个(比拟费事)是应用包装器扩大元组。这样,咱们即可以docstring正在此包装器中界说。例如,请思考如下代码片断:

_Color = namedtuple("Color", "r g b alpha")

class Color(_Color):
    """A namedtuple that represents a color.
    It has 4 fields:
    r - red
    g - green
    b - blue
    alpha - the alpha channel
    """

>>> print(Color.__doc__)
A namedtuple that represents a color.
    It has 4 fields:
    r - red
    g - green
    b - blue
    alpha - the alpha channel
>>> help(Color)
Help on class Color in module __main__:

class Color(Color)
 |  Color(r, g, b, alpha)
 |  
 |  A namedtuple that represents a color.
 |  It has 4 fields:
 |  r - red
 |  g - green
 |  b - blue
 |  alpha - the alpha channel
 |  
 |  Method resolution order:
 |      Color
 |      Color
 |      builtins.tuple
 |      builtins.object
 |  
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)复制代码

如上,经过承继_Color元组,咱们为namedtupe增加了一个__doc__属性。

增加的第二种办法,间接设置__doc__属性。这类办法没有需求扩大元组。

>>> Color.__doc__ = """A namedtuple that represents a color.
    It has 4 fields:
    r - red
    g - green
    b - blue
    alpha - the alpha channel
    """复制代码

留意,这些办法仅实用于Python 3+

限于篇幅,先到这下篇持续。

相干收费学习保举:python教程(视频)

以上就是Python数据构造:一个被低估的Namedtuple(一)的具体内容,更多请存眷资源魔其它相干文章!

标签: Python python教程 python编程 python使用问题

抱歉,评论功能暂时关闭!