Maison >développement back-end >Tutoriel Python >Structure de données Python : un Namedtuple sous-estimé (2)

Structure de données Python : un Namedtuple sous-estimé (2)

coldplay.xixi
coldplay.xixiavant
2020-10-20 17:10:303439parcourir

La colonne

tutoriel vidéo Python continue de vous amener à comprendre la structure de données Namedtuple de Python.

Structure de données Python : un Namedtuple sous-estimé (2)

Partie 1 Structure de données Python : un Namedtuple sous-estimé (1) Après avoir parlé d'une utilisation de base de Namedtuple, cet article continue.

Quelle est la différence entre les tuples nommés et les classes de données ?

Fonction

Avant Python 3.7, un simple conteneur de données pouvait être créé à l'aide de l'une des méthodes suivantes :

  • namedtuple
  • Classe générale
  • Bibliothèques tierces, attrs

Si vous souhaitez utiliser des cours réguliers, cela signifie que vous devrez mettre en œuvre quelques méthodes. Par exemple, une classe ordinaire aurait besoin d'une méthode __init__ pour définir les propriétés lors de l'instanciation de la classe. Si vous souhaitez que la classe soit hachable, cela signifie implémenter vous-même une méthode __hash__. Afin de comparer différents objets, vous devez également implémenter une méthode __eq__. Enfin, pour simplifier le débogage, vous avez besoin d'une méthode __repr__.

Utilisons des cours réguliers pour mettre en œuvre notre cas d'utilisation des couleurs.

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

Comme ci-dessus, vous devez implémenter de nombreuses méthodes. Vous avez juste besoin d’un conteneur pour conserver vos données sans vous soucier des détails gênants. Encore une fois, une différence clé dans la raison pour laquelle les gens préfèrent les classes d'implémentation est que les classes régulières sont mutables.

En fait, le PEP qui a introduit 数据类(Data Class) les appelle des « tuples nommés mutables avec des valeurs par défaut » (Note du traducteur : classe de données introduite dans python 3.7, référence : docs.python.org/zh-cn / 3/lib…

Maintenant, voyons comment faire avec 数据类

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

Wow ! Puisqu'il n'y a pas de __init__, il suffit de le suivre. . De plus, il doit être annoté avec des indications de type

En plus d'être mutable, la classe data peut fournir des champs facultatifs prêts à l'emploi. Disons que notre classe Color n'a pas besoin de champ alpha. peut faire en sorte que

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

l'instancier comme ceci :

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

Puisqu'ils sont mutables, nous pouvons modifier tous les champs que nous voulons. L'instancier comme ceci :

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

En revanche, <.> n'a pas de champs optionnels par défaut. Pour les ajouter, nous avons besoin d'une petite astuce et de quelques conseils de métaprogrammation : Pour ajouter une méthode namedtuple, vous devez la rendre immuable en définissant

sur

 : __hash__

@dataclass(unsafe_hash=True)class Color:
    ...复制代码
unsafe_hash Une autre différence est que le déballage est une fonctionnalité native des tuples nommés (citoyen de première classe) Si vous voulez True avoir le même comportement, vous devez implémenter votre propre
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)复制代码

Comparaison des performances 数据类. 🎜>

Il ne suffit pas de comparer les fonctions, les classes nommées et les classes de données présentent également des différences de performances. La différence est basée sur une implémentation Python pure de dict, ce qui les rend plus rapides lors de l'accès aux champs. des tuples étendus réguliers, ce qui signifie que leur implémentation est basée sur un code C plus rapide et a une occupation de mémoire plus petite

Pour démontrer cela, envisagez d'exécuter cette expérience sur 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复制代码
Comme ci-dessus, les données. les classes sont légèrement plus rapides pour accéder aux champs, mais elles sont nametuple et occupent plus d'espace mémoire

Comment ajouter des indices de type à Nametuple

Les classes de données utilisent des indices de type par défaut. en les important sur des tuples nommés. En héritant de celui-ci, nous pouvons annoter des tuples de couleur

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

Un autre détail qui n'a peut-être pas été remarqué est que cette approche nous permet également d'utiliser docstring si nous tapons help(Color) nous le ferons. pouvoir voir.

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.复制代码
Comment ajouter une valeur facultative par défaut à nomméetuple

Dans la section précédente, nous avons appris que les classes de données peuvent avoir des valeurs facultatives. Aussi, j'ai mentionné que pour imiter le même comportement

certaines modifications techniques sont nécessaires. Il s'avère que nous pouvons utiliser l'héritage comme le montre l'exemple suivant.

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

Conclusionnamedtuple

Les tuples sont une structure de données très puissante. Ils rendent notre code plus propre et plus fiable. Malgré la rude concurrence des nouveaux

, ils ont encore une tonne de scènes disponibles. Dans ce tutoriel, nous avons appris plusieurs façons d'utiliser

et nous espérons que vous pourrez les utiliser.

数据类namedtuples

Recommandations d'apprentissage gratuites associées :

Tutoriel vidéo Python

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer

Articles Liés

Voir plus