# `dataclasses` — Clases de datos

Source code: Lib/dataclasses.py

Este módulo provee un decorador y funciones para añadir los métodos especiales automáticamente, como por ejemplo `__init__()` y `__repr__()`, a clases definidas por el usuario. Fue originalmente descrito en PEP 557.

Cada variable miembro a utilizar en estos métodos generados son definidas teniendo en cuenta PEP 526 para anotaciones de tipo. Por ejemplo en este código:

    from dataclasses import dataclass

    @dataclass
    class InventoryItem:
        """Class for keeping track of an item in inventory."""
        name: str
        unit_price: float
        quantity_on_hand: int = 0

        def total_cost(self) -> float:
            return self.unit_price * self.quantity_on_hand

Añadirá, además de otros métodos, un `__init__()` con la siguiente forma:

    def __init__(self, name: str, unit_price: float, quantity_on_hand: int=0):
        self.name = name
        self.unit_price = unit_price
        self.quantity_on_hand = quantity_on_hand

Es importante observar que este método es añadido a la clase automáticamente; está implícito en la definición de `InventoryItem` implementada arriba.

Nuevo en la versión 3.7.

## Decoradores, clases y funciones del módulo

`@``dataclasses.``dataclass`(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)

  Esta función es un decorator utilizado para añadir los métodos especiales generados a las clases, como se describe a continuación.

  El decorador `dataclass()` examina la clase para encontrar `field`s. Un `field` se define como una variable de clase que tiene una anotación de variable. A excepción de los dos casos descriptos debajo, nada en `dataclass()` examina el tipo especificado en la anotación de variable.

  El orden de los campos en los métodos generados es el mismo en el que se encuentran en la definición de la clase.

  El decorador `dataclass()` añade varios métodos mágicos «dunder» a la clase, descripto a continuación. Si algo de los métodos añadidos ya existe en la definición de la clase, el comportamiento dependerá del parámetro. El decorador retorna la misma clase que es llamada, no crea una nueva.

  Si `dataclass()` es llamada sin parámetros, actúa con los valores por defecto documentados aquí. Específicamente, los siguientes tres usos de `dataclass()` son equivalentes:

      @dataclass
      class C:
          ...

      @dataclass()
      class C:
          ...

      @dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
      class C:
         ...

  Los parámetros de `dataclass()` son:

  - `init`: Si es verdadero (valor por defecto) el método `__init__()` es generado.

    Si la clase ya define `__init__()`, este parámetro es ignorado.

  - `repr`: Si es verdadero (valor por defecto) el método `__repr__()` es generado. La cadena de caracteres generada por repr tendrá el nombre de la clase y el repr de cada campo en el mismo orden en el que están definidos en la clase; es posible especificar que ciertos campos sean ignorados por este método. Por ejemplo: `InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)`.

    Si la clase ya define `__repr__()`, este parámetro es ignorado.

  - `eq`: Si es verdadero (por defecto) el método `__eq__()` es generado. Este método compara entre instancias de la clase representando cada una de ellas con una tupla, siendo los elementos de la misma los campos de la clase ubicados en el mismo orden en el que fueron definidos (dos tuplas son iguales si y sólo si sus campos son iguales).

    Si la clase ya define `__eq__()`, este parámetro es ignorado.

  - `order`: Si es verdadero ( `False` es el valor por defecto), `__lt__()`, `__le__()`, `__gt__()` y `__ge__()` son generados. Estos permiten comparaciones entre instancias de la clase como si fueran una tupla de sus campos (en orden). Ambas instancias a comparar deben ser del mismo tipo. Si `order` es verdadero y `eq` falso, lanza la excepción `ValueError`.

    Si la clase ya define alguno de los siguientes métodos: `__lt__()`, `__le__()`, `__gt__()` o `__ge__()`, lanza la excepción `TypeError`.

  - `unsafe_hash`: Si `False` (por defecto), se genera el método `__hash__()` de acuerdo a los valores de `eq` y `frozen` definidos.

    `__hash__()` es utilizado por el método incorporado `hash()` y cuando los objetos definidos por la clase son añadidos a colecciones hash, como por ejemplo diccionarios y conjuntos. Una clase con el método `__hash__()` definido implica que sus instancias son inmutables. La mutabilidad es una propiedad compleja, ya que depende de: cómo el programador utilice el objeto, la existencia y comportamiento de `__eq__()` y del valor asignado a las banderas `eq` y `frozen` en el decorador `dataclass()`.

    `dataclass()` no añade por defecto (de forma implícita) el método `__hash__()` a menos que sea seguro hacerlo, tampoco añade o cambia un método `__hash__()` explícitamente ya definido. Definir el atributo de clase `__hash__ = None` tiene un significado específico en Python, descripto en la documentación dedicada a `__hash__()`.

    If `__hash__()` is not explicit defined, or if it is set to `None`, then `dataclass()` may add an implicit `__hash__()` method. Although not recommended, you can force `dataclass()` to create a `__hash__()` method with `unsafe_hash=True`. This might be the case if your class is logically immutable but can nonetheless be mutated. This is a specialized use case and should be considered carefully.

    A continuación se explican las reglas que aplican en la creación implícita del método `__hash__()`. Observar que no es compatible definir explícitamente `__hash__()` en su clase y a su vez asignar `unsafe_hash=True`; esto lanza la excepción `TypeError`.

    Si `eq` y `frozen` son verdaderos, `dataclass()` genera por defecto un método `hash()` por ti. En el caso que `eq` sea verdadero y `frozen` falso, a `__hash__()` se le asigna `None`, en consecuencia será unhashable (lo cual es deseable, ya que es mutable). Si `eq` es falso `__hash__()` permanece sin cambios, por lo tanto en este caso aplica el uso del método `hash()` heredado de la superclase (sólo si la superclase es `object`, esto significa que cae en manos del hashing basado en el id de los objetos).

  - `frozen`: Si es verdadero (el valor por defecto es `False`), cualquier asignación a un campo de la clase lanza una excepción. Esto emula el comportamiento de las instancias frozen de sólo lectura. Si `__setattr__()` o `___delattr__()` son definidos en la clase, lanzará la excepción `TypeError`. Esto es ampliado debajo.

  Los `fields` pueden, opcionalmente, especificar un valor por defecto:

      @dataclass
      class C:
          a: int       # 'a' has no default value
          b: int = 0   # assign a default value for 'b'

  En este ejemplo, `a` y `b` serán incluidos en el método generado `__init__()`, el cual es definido como sigue:

      def __init__(self, a: int, b: int = 0):

  Si, en la definición de una clase, a un campo con valor por defecto le sigue un campo sin valor por defecto será lanzada la excepción `TypeError`. Esto aplica también en la definición de una clase mediante herencia.

`dataclasses.``field`(*, default=MISSING, default_factory=MISSING, repr=True, hash=None, init=True, compare=True, metadata=None)

  Para casos de uso común, estas funcionalidades son suficientes. Sin embargo, existen otras características de dataclass que requieren información adicional en ciertos campos. Para satisfacer esta necesidad, es posible reemplazar cualquier valor por defecto de un campo mediante una llamada a la función `field()`. Por ejemplo:

      @dataclass
      class C:
          mylist: List[int] = field(default_factory=list)

      c = C()
      c.mylist += [1, 2, 3]

  Como se muestra arriba, el valor `MISSING` es un objeto centinela utilizado para detectar si los parámetros `default` y `default_factory` son provistos. Este objeto centinela es utilizado ya que `None` es un valor válido para `default`. Ningún procedimiento debe utilizar directamente el valor `MISSING`.

  Los parámetros de `field()` son:

  - `default`: Si es provisto, este será el valor por defecto para este campo. Es necesario que sea definido ya que la propia llamada `field()` reemplaza automáticamente la posición del valor default.

  - `default_factory`: Si es provisto, debe ser un objeto invocable sin argumentos el cual será llamado cuando el valor por defecto de este campo sea necesario. Además de otros propósitos, puede ser utilizado para especificar campos con valores por defecto mutables, como se explica a continuación. Especificar tanto `default` como `default_factory` resulta en un error.

  - `init`: Si es verdadero (por defecto), este campo es incluido como parámetro del método `__init__()` generado.

  - `repr`: Si es verdadero (por defecto), este campo es incluido en la cadena de caracteres que retorna el método `__repr__()` generado.

  - `compare`: Si es verdadero (por defecto), este campo es incluido en los métodos de comparación generados: `__eq__()`, `__gt__()` y otros.

  - `hash`: Su valor puede ser de tipo booleano o `None`. Si es verdadero, este campo es incluido en el método `__hash__()` generado. Si `None` (por defecto), utiliza el valor de `compare`; normalmente éste es el comportamiento esperado, un campo debería ser considerado para el hash si el mismo es compatible con operaciones de comparación. Está desaconsejado establecer este valor como otro que no sea `None`.

    Una posible razón para definir `hash=False` y `compare=True` podría ser en el caso que computar el valor hash para dicho campo es costoso, es necesario que tenga definido métodos de comparación y además otros campos contribuyen a determinar el tipo del valor hash. Aunque un campo sea excluido del hash, puede ser sujeto a comparaciones.

  - `metadata`: This can be a mapping or None. None is treated as an empty dict. This value is wrapped in `MappingProxyType()` to make it read-only, and exposed on the `Field` object. It is not used at all by Data Classes, and is provided as a third-party extension mechanism. Multiple third-parties can each have their own key, to use as a namespace in the metadata.

  Si el valor por defecto de un campo es especificado por una llamada a `field()`, los atributos de clase para este campo serán reemplazados por los especificados en el valor `default`. Si el valor de `default` no es provisto, el atributo de clase será eliminado. La idea es que, después que la ejecución del decorador `dataclass()`, todos los atributos de la clase contengan los valores por defecto de cada campo, como si fueran definidos uno por uno. Por ejemplo, luego de:

      @dataclass
      class C:
          x: int
          y: int = field(repr=False)
          z: int = field(repr=False, default=10)
          t: int = 20

  El atributo `C.z` será `10`, el atributo `C.t` será `20` y los atributos `C.x` y `C.y` estarán sin definir.

class `dataclasses.``Field`

  Los objetos `Field` describen cada campo definido. Estos objetos son creados implícitamente y son retornados por el método `fields()` definido en este módulo (explicado más abajo). Los usuarios no deben instanciar un objeto `Field` directamente. Sus atributos documentados son:

  > - `name`: Nombre del campo.

  > - `type`: El tipo del campo.

  > - `default`, `default_factory`, `init`, `repr`, `hash`, `compare` y `metadata` tienen los mismos valores y significados respecto a la declaración de `field()` (arriba).

  Pueden existir otros atributos, pero son privados y no deberían ser examinados ni depender de ellos.

`dataclasses.``fields`(class_or_instance)

  Returns a tuple of `Field` objects that define the fields for this dataclass. Accepts either a dataclass, or an instance of a dataclass. Raises `TypeError` if not passed a dataclass or instance of one. Does not return pseudo-fields which are `ClassVar` or `InitVar`.

`dataclasses.``asdict`(instance, *, dict_factory=dict)

  Converts the dataclass `instance` to a dict (by using the factory function `dict_factory`). Each dataclass is converted to a dict of its fields, as `name: value` pairs. dataclasses, dicts, lists, and tuples are recursed into. For example:

      @dataclass
      class Point:
           x: int
           y: int

      @dataclass
      class C:
           mylist: List[Point]

      p = Point(10, 20)
      assert asdict(p) == {'x': 10, 'y': 20}

      c = C([Point(0, 0), Point(10, 4)])
      assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}

  Raises `TypeError` if `instance` is not a dataclass instance.

`dataclasses.``astuple`(instance, *, tuple_factory=tuple)

  Converts the dataclass `instance` to a tuple (by using the factory function `tuple_factory`). Each dataclass is converted to a tuple of its field values. dataclasses, dicts, lists, and tuples are recursed into.

  Continuing from the previous example:

      assert astuple(p) == (10, 20)
      assert astuple(c) == ([(0, 0), (10, 4)],)

  Raises `TypeError` if `instance` is not a dataclass instance.

`dataclasses.``make_dataclass`(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)

  Creates a new dataclass with name `cls_name`, fields as defined in `fields`, base classes as given in `bases`, and initialized with a namespace as given in `namespace`. `fields` is an iterable whose elements are each either `name`, `(name, type)`, or `(name, type, Field)`. If just `name` is supplied, `typing.Any` is used for `type`. The values of `init`, `repr`, `eq`, `order`, `unsafe_hash`, and `frozen` have the same meaning as they do in `dataclass()`.

  This function is not strictly required, because any Python mechanism for creating a new class with `__annotations__` can then apply the `dataclass()` function to convert that class to a dataclass. This function is provided as a convenience. For example:

      C = make_dataclass('C',
                         [('x', int),
                           'y',
                          ('z', int, field(default=5))],
                         namespace={'add_one': lambda self: self.x + 1})

  Is equivalent to:

      @dataclass
      class C:
          x: int
          y: 'typing.Any'
          z: int = 5

          def add_one(self):
              return self.x + 1

`dataclasses.``replace`(instance, **changes)

  Creates a new object of the same type of `instance`, replacing fields with values from `changes`. If `instance` is not a Data Class, raises `TypeError`. If values in `changes` do not specify fields, raises `TypeError`.

  The newly returned object is created by calling the `__init__()` method of the dataclass. This ensures that `__post_init__()`, if present, is also called.

  Init-only variables without default values, if any exist, must be specified on the call to `replace()` so that they can be passed to `__init__()` and `__post_init__()`.

  It is an error for `changes` to contain any fields that are defined as having `init=False`. A `ValueError` will be raised in this case.

  Be forewarned about how `init=False` fields work during a call to `replace()`. They are not copied from the source object, but rather are initialized in `__post_init__()`, if they’re initialized at all. It is expected that `init=False` fields will be rarely and judiciously used. If they are used, it might be wise to have alternate class constructors, or perhaps a custom `replace()` (or similarly named) method which handles instance copying.

`dataclasses.``is_dataclass`(class_or_instance)

  Return `True` if its parameter is a dataclass or an instance of one, otherwise return `False`.

  If you need to know if a class is an instance of a dataclass (and not a dataclass itself), then add a further check for `not isinstance(obj, type)`:

      def is_dataclass_instance(obj):
          return is_dataclass(obj) and not isinstance(obj, type)

## Post-init processing

The generated `__init__()` code will call a method named `__post_init__()`, if `__post_init__()` is defined on the class. It will normally be called as `self.__post_init__()`. However, if any `InitVar` fields are defined, they will also be passed to `__post_init__()` in the order they were defined in the class. If no `__init__()` method is generated, then `__post_init__()` will not automatically be called.

Among other uses, this allows for initializing field values that depend on one or more other fields. For example:

    @dataclass
    class C:
        a: float
        b: float
        c: float = field(init=False)

        def __post_init__(self):
            self.c = self.a + self.b

See the section below on init-only variables for ways to pass parameters to `__post_init__()`. Also see the warning about how `replace()` handles `init=False` fields.

## Class variables

One of two places where `dataclass()` actually inspects the type of a field is to determine if a field is a class variable as defined in PEP 526. It does this by checking if the type of the field is `typing.ClassVar`. If a field is a `ClassVar`, it is excluded from consideration as a field and is ignored by the dataclass mechanisms. Such `ClassVar` pseudo-fields are not returned by the module-level `fields()` function.

## Init-only variables

The other place where `dataclass()` inspects a type annotation is to determine if a field is an init-only variable. It does this by seeing if the type of a field is of type `dataclasses.InitVar`. If a field is an `InitVar`, it is considered a pseudo-field called an init-only field. As it is not a true field, it is not returned by the module-level `fields()` function. Init-only fields are added as parameters to the generated `__init__()` method, and are passed to the optional `__post_init__()` method. They are not otherwise used by dataclasses.

For example, suppose a field will be initialized from a database, if a value is not provided when creating the class:

    @dataclass
    class C:
        i: int
        j: int = None
        database: InitVar[DatabaseType] = None

        def __post_init__(self, database):
            if self.j is None and database is not None:
                self.j = database.lookup('j')

    c = C(10, database=my_database)

In this case, `fields()` will return `Field` objects for `i` and `j`, but not for `database`.

## Frozen instances

It is not possible to create truly immutable Python objects. However, by passing `frozen=True` to the `dataclass()` decorator you can emulate immutability. In that case, dataclasses will add `__setattr__()` and `__delattr__()` methods to the class. These methods will raise a `FrozenInstanceError` when invoked.

There is a tiny performance penalty when using `frozen=True`: `__init__()` cannot use simple assignment to initialize fields, and must use `object.__setattr__()`.

## Inheritance

When the dataclass is being created by the `dataclass()` decorator, it looks through all of the class’s base classes in reverse MRO (that is, starting at `object`) and, for each dataclass that it finds, adds the fields from that base class to an ordered mapping of fields. After all of the base class fields are added, it adds its own fields to the ordered mapping. All of the generated methods will use this combined, calculated ordered mapping of fields. Because the fields are in insertion order, derived classes override base classes. An example:

    @dataclass
    class Base:
        x: Any = 15.0
        y: int = 0

    @dataclass
    class C(Base):
        z: int = 10
        x: int = 15

The final list of fields is, in order, `x`, `y`, `z`. The final type of `x` is `int`, as specified in class `C`.

The generated `__init__()` method for `C` will look like:

    def __init__(self, x: int = 15, y: int = 0, z: int = 10):

## Default factory functions

> If a `field()` specifies a `default_factory`, it is called with zero arguments when a default value for the field is needed. For example, to create a new instance of a list, use:

>     mylist: list = field(default_factory=list)

> If a field is excluded from `__init__()` (using `init=False`) and the field also specifies `default_factory`, then the default factory function will always be called from the generated `__init__()` function. This happens because there is no other way to give the field an initial value.

## Mutable default values

> Python stores default member variable values in class attributes. Consider this example, not using dataclasses:

>     class C:
>         x = []
>         def add(self, element):
>             self.x.append(element)

>     o1 = C()
>     o2 = C()
>     o1.add(1)
>     o2.add(2)
>     assert o1.x == [1, 2]
>     assert o1.x is o2.x

> Note that the two instances of class `C` share the same class variable `x`, as expected.

> Using dataclasses, if this code was valid:

>     @dataclass
>     class D:
>         x: List = []
>         def add(self, element):
>             self.x += element

> it would generate code similar to:

>     class D:
>         x = []
>         def __init__(self, x=x):
>             self.x = x
>         def add(self, element):
>             self.x += element

>     assert D().x is D().x

> This has the same issue as the original example using class `C`. That is, two instances of class `D` that do not specify a value for `x` when creating a class instance will share the same copy of `x`. Because dataclasses just use normal Python class creation they also share this behavior. There is no general way for Data Classes to detect this condition. Instead, dataclasses will raise a `TypeError` if it detects a default parameter of type `list`, `dict`, or `set`. This is a partial solution, but it does protect against many common errors.

> Using default factory functions is a way to create new instances of mutable types as default values for fields:

>     @dataclass
>     class D:
>         x: list = field(default_factory=list)

>     assert D().x is not D().x

## Exceptions

exception `dataclasses.``FrozenInstanceError`

  Raised when an implicitly defined `__setattr__()` or `__delattr__()` is called on a dataclass which was defined with `frozen=True`.