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

资源魔 31 0

python视频教程栏目持续带各人理解Python数据构造的Namedtuple。

上篇Python数据构造:一个被低估的Namedtuple(一)讲了namedtuple的一些根本用法,本篇持续。

namedtuples以及数据类(Data Class)之间有甚么区分?

性能

正在Python 3.7以前,可以使用如下任一办法创立一个简略的数据容器:

  • namedtuple
  • 惯例类
  • 第三方库,attrs

假如您想应用惯例类,那象征着您将必需完成几个办法。例如,惯例类将需求一种__init__办法来正在类实例化时期设置属性。假如您心愿该类是可哈希的,则象征着本人完成一个__hash__办法。为了比拟没有同的工具,还需求__eq__完成一个办法。最初,为了简化调试,您需求一种__repr__办法。

让咱们应用惯例类来完成下咱们的颜色用例。

class Color:
    """A regular class that represents a color."""

    def __init__(self, r, g, b, alpha=0.0):
        self.r = r
        self.g = g
        self.b = b
        self.alpha = alpha    def __hash__(self):
        return hash((self.r, self.g, self.b, self.alpha))    def __repr__(self):
        return "{0}({1}, {2}, {3}, {4})".format(
            self.__class__.__name__, self.r, self.g, self.b, self.alpha
        )    def __eq__(self, other):
        if not isinstance(other, Color):            return False
        return (
            self.r == other.r            and self.g == other.g            and self.b == other.b            and self.alpha == other.alpha
        )复制代码

如上,你需求完成很多多少办法。您只要要一个容器来为您保留数据,而不用担忧扩散留意力的细节。一样,人们偏幸完成类的一个要害区分是惯例类是可变的。

实际上,引入数据类(Data Class)的PEP将它们称为“具备默许值的可变namedtuple”(译者注:Data Class python 3.7引入,参考:docs.python.org/zh-cn/3/lib…

如今,让咱们看看若何用数据类来完成。

from dataclasses import dataclass
...@dataclassclass Color:
    """A regular class that represents a color."""
    r: float
    g: float
    b: float
    alpha: float复制代码

哇!就是这么简略。因为不__init__,您只要正在docstring前面界说属性便可。别的,必需应用类型提醒对其进行正文。

除了了可变以外,数据类还能够开箱即用提供可选字段。假定咱们的Color类没有需求alpha字段。而后咱们能够设置为可选。

from dataclasses import dataclassfrom typing import Optional
...@dataclassclass Color:
    """A regular class that represents a color."""
    r: float
    g: float
    b: float
    alpha: Optional[float]复制代码

咱们能够像这样实例化它:

>>> blue = Color(r=0, g=0, b=255)复制代码

因为它们是可变的,因而咱们能够更改所需的任何字段。咱们能够像这样实例化它:

>>> blue = Color(r=0, g=0, b=255)
>>> blue.r = 1
>>> # 能够设置更多的属性字段
>>> blue.e = 10复制代码

相较之下,namedtuple默许状况下不可选字段。要增加它们,咱们需求一点技术以及一些元编程。

提醒:要增加__hash__办法,您需求经过将设置unsafe_hash为使其不成变True

@dataclass(unsafe_hash=True)class Color:
    ...复制代码

另外一个区分是,拆箱(unpacking)是namedtuples的自带的性能(first-class citizen)。假如心愿数据类具备相反的行为,则必需完成本人。

from dataclasses import dataclass, astuple
...@dataclassclass Color:
    """A regular class that represents a color."""
    r: float
    g: float
    b: float
    alpha: float    def __iter__(self):
        yield from dataclasses.astuple(self)复制代码

功能比拟

仅比拟性能是不敷的,namedtuple以及数据类正在功能上也有所没有同。数据类基于纯Python完成dict。这使患上它们正在拜访字段时更快。另外一方面,namedtuples只是惯例的扩大tuple。这象征着它们的完成基于更快的C代码并具备较小的内存占用量。

为了证实这一点,请思考正在Python 3.8.5上进行此试验。

In [6]: import sys

In [7]: ColorTuple = namedtuple("Color", "r g b alpha")

In [8]: @dataclass
   ...: class ColorClass:
   ...:     """A regular class that represents a color."""
   ...:     r: float
   ...:     g: float
   ...:     b: float
   ...:     alpha: float
   ...: 

In [9]: color_tup = ColorTuple(r=50, g=205, b=50, alpha=1.0)

In [10]: color_cls = ColorClass(r=50, g=205, b=50, alpha=1.0)

In [11]: %timeit color_tup.r36.8 ns ± 0.109 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [12]: %timeit color_cls.r38.4 ns ± 0.112 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [15]: sys.getsizeof(color_tup)
Out[15]: 72In [16]: sys.getsizeof(color_cls) + sys.getsizeof(vars(color_cls))
Out[16]: 152复制代码

如上,数据类正在中拜访字段的速率稍快一些,然而它们比nametuple占用更多的内存空间。

若何将类型提醒增加到 namedtuple

数据类默许应用类型提醒。咱们也能够将它们放正在namedtuples上。经过导入Namedtuple正文类型并从中承继,咱们能够对Color元组进行正文。

from typing import NamedTuple
...class Color(NamedTuple):
    """A namedtuple that represents a color."""
    r: float
    g: float
    b: float
    alpha: float复制代码

另外一个可能未惹起留意的细节是,这类形式还容许咱们应用docstring。假如输出,help(Color)咱们将可以看到它们。

Help on class Color in module __main__:class Color(builtins.tuple)
 |  Color(r: float, g: float, b: float, alpha: Union[float, NoneType])
 |  
 |  A namedtuple that represents a color.
 |  
 |  Method resolution order:
 |      Color
 |      builtins.tuple
 |      builtins.object
 |  
 |  Methods defined here:
 |  
 |  __getnewargs__(self)
 |      Return self as a plain tuple.  Used by copy and pickle.
 |  
 |  __repr__(self)
 |      Return a nicely formatted representation string
 |  
 |  _asdict(self)
 |      Return a new dict which maps field names to their values.复制代码

若何将可选的默许值增加到 namedtuple

正在上一节中,咱们理解了数据类能够具备可选值。另外,我提到要模拟上的相反行为,namedtuple需求进行一些技术修正操作。现实证实,咱们能够应用承继,以下例所示。

from collections import namedtupleclass Color(namedtuple("Color", "r g b alpha")):
    __slots__ = ()    def __new__(cls, r, g, b, alpha=None):
        return super().__new__(cls, r, g, b, alpha)>>> c = Color(r=0, g=0, b=0)>>> c
Color(r=0, g=0, b=0, alpha=None)复制代码

论断

元组是一个十分弱小的数据构造。它们使咱们的代码更清洁,更牢靠。虽然与新的数据类竞争强烈,但他们仍有年夜量的场景可用。正在本教程中,咱们学习了应用namedtuples的几种办法,心愿您能够应用它们。

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

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

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

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