ホームページ  >  記事  >  バックエンド開発  >  Python データ構造: 過小評価されている Namedtuple (2)

Python データ構造: 過小評価されている Namedtuple (2)

coldplay.xixi
coldplay.xixi転載
2020-10-20 17:10:303332ブラウズ

Python ビデオ チュートリアルこのコラムでは引き続き、Python データ構造の Namedtuple について理解していきます。

Python データ構造: 過小評価されている Namedtuple (2)

パート 1Python データ構造: 過小評価されている Namedtuple (1)namedtuple の基本的な使用法について説明した後、この記事は続きます。

名前付きタプルとデータ クラスの違いは何ですか?

関数

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 Classes を導入する PEP では、それらを「デフォルト値を持つ可変の名前付きタプル」と呼んでいます (翻訳者注: Python 3.7 で導入されたデータ クラス、参考: docs.python.org /zh-cn/3/lib…

さあ、dataclasses.

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

を使ってそれを行う方法を見てみましょう! それは簡単です。 __init__ では、docstring の後にプロパティを定義するだけです。さらに、プロパティには型ヒントの注釈を付ける必要があります。

データ クラスは、変更可能であることに加えて、すぐに使用できるオプションのフィールドが提供されていますColor クラスにアルファ フィールドが必要ないとします。その後、それをオプションにできます。

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_hashTrue に設定して不変にする必要があります:

@dataclass(unsafe_hash=True)class Color:
    ...复制代码
もう 1 つの違いは次のとおりです。その解凍は名前付きタプル (第一級市民) の組み込み関数です。

data クラス に同じ動作を持たせたい場合は、自分で実装する必要があります。パフォーマンスの比較

関数を比較するだけでは不十分で、namedtuple とデータ クラスのパフォーマンスも異なります。データ クラスは純粋な Python ベースの dict を実装しています。これにより、フィールドへのアクセスが高速になります。一方、Namedtuple は、は単なる通常の拡張タプルです。これは、それらの実装が高速な C コードに基づいており、メモリ フットプリントが小さいことを意味します。

証明するには、この時点で、この実験を Python 3.8.5 で実行することを検討してください。

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)复制代码
上記のように、データ クラスはフィールドへのアクセスがわずかに高速ですが、名前タプルよりも多くのメモリ領域を消費します。

名前付きタプルに型ヒントを追加する方法

データ クラスは型を使用しますヒントはデフォルトで設定されています。名前付きタプルに配置することもできます。名前付きタプル注釈タイプをインポートし、それを継承することで、カラータプルに注釈を付けることができます。

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复制代码

気づかれていないかもしれないもう 1 つの詳細は、このアプローチにより、 docstring を使用します。 help(Color) と入力すると表示されます。

from typing import NamedTuple
...class Color(NamedTuple):
    """A namedtuple that represents a color."""
    r: float
    g: float
    b: float
    alpha: float复制代码
オプションのデフォルト値をnamedtupleに追加する方法

前のセクションでは、データクラスがオプションの値を持つことができることを学びました。さらに、同じ動作を模倣するには、

namedtuple

にいくつかの技術的な変更が必要であることも述べました。次の例に示すように、継承を使用できることがわかります。

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.复制代码
結論タプルは非常に強力なデータ構造です。これらにより、コードがよりクリーンになり、信頼性が高まります。新しい

データ クラス

との激しい競争にもかかわらず、依然として多数のシナリオが利用可能です。このチュートリアルでは、

namedtuples の使用方法をいくつか学びましたので、ぜひご活用ください。

関連する無料学習の推奨事項:

Python ビデオ チュートリアル

以上がPython データ構造: 過小評価されている Namedtuple (2)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。