---
title: Vistas de los diccionarios de Python: keys, values e items
url: https://jarroba.com/vistas-de-los-diccionarios-de-python-keys-values-e-items/
author: Ramón Invarato
date: 2019-04-14
modified: 2026-10-21
language: es
license: CC BY-NC-SA 3.0 (https://creativecommons.org/licenses/by-nc-sa/3.0/) — attribution: "Vistas de los diccionarios de Python: keys, values e items", Ramón Invarato, jarroba.com
categories: Lenguajes de Programación
tags: dict, items, ItemsView, iterable, keys, KeysView, list, Mapping, Set, Sized, values, ValuesView, Views
repository: https://github.com/Invarato/JarrobaPython/tree/master/vistas_de_los_diccionarios
---

# Vistas de los diccionarios de Python: keys, values e items

> En las Views de Python se puede modificar algo de su diccionario asociado (algún valor o clave) y se reflejará en el interior de las Views.

Las “**Vistas**” (“Views” en inglés) de los datos que están dentro de los diccionarios (Mapping) en Python son muy importantes, tanto que se usan muchísimo (aunque no nos estemos dando cuenta de que lo usamos) y, sin embargo, no utilizamos su gran potencial. Un óptimo flujo de nuestros datos para que el procesamiento sea rápido y un consumo mínimo de recursos requiere conocer estos secretos.

 

La principal cualidad de las **Vistas** es que **si modificamos algo de su diccionario asociado** (algún valor o clave), **se reflejará** en el interior de **las vistas** (ejemplos más adelante).

 

**Código en GitHub**(Recomiendo primero leer el artículo y descargar/clonar el código al final)**:** [Ver en GitHub**Invarato/JarrobaPython** / vistas_de_los_diccionarios](https://github.com/Invarato/JarrobaPython/tree/master/vistas_de_los_diccionarios)

 

Para que se entienda a la primera, para los ejemplos usaré el siguiente diccionario que tiene como clave una fruta (voy a escribir la clave en MAYÚSCULA para diferenciarla más fácilmente del valor que escribiré en minúscula) y como valor el árbol al que pertenece la fruta:

 

```python
mi_diccionario = {
    "MANZANA": "Manzano",
    "UVA": "Vid",
    "PERA": "Peral",
}
```

 

De este diccionario podremos querer “Ver” (**Obtener Vistas en Python 3**):

 
- Todas las claves con **keys()**, que **devuelve** un objeto de tipo **KeysView**.

 

```python
vista_claves = mi_diccionario.keys()
```

 
- Todos los valores con**values()**, que **devuelve** un objeto de tipo **ValuesView**.

 

```python
vista_valores = mi_diccionario.values()
```

 
- Todas las claves asociadas con sus valores (en tuplas) con **items()**, que **devuelve** un objeto de tipo **ItemsView**.

 

```python
vista_items = mi_diccionario.items()
```

 

 

Nota

 

#### **Vistas en Python 2**

 

También se pueden obtener las vistas en Python 2, pero no si se utilizan los métodos **keys(), values() o items()** pues devuelven listados (o iteritems() que devuelve un “iterador”), estos métodos **en Python 2 NO devuelven Vistas**.

 

Para devolver una Vista en Python 2 es parecido, pero es necesario usar los métodos:

 
- **viewkeys():** **devuelve** un objeto de tipo **KeysView**.

 

```python
vista_claves = mi_diccionario.viewkeys()
```

 
- **viewvalues()**: **devuelve** un objeto de tipo **ValuesView**.

 

```python
vista_valores = mi_diccionario.viewvalues()
```

 
- **viewitems()**: **devuelve** un objeto de tipo **ItemsView**.

 

```python
vista_items = mi_diccionario.viewitems()
```

 

 

## Clases de las Vistas (Views)

 

Como hemos comentado las clases de las vistas son:

 
- Vista de las Claves (**KeysView**)
- Vista de los Valores (**ValuesView**)
- Vista de los Ítems (**ItemsView**)

 

Y estas tres **heredan** de la clase Vista del Mapeo (**MappingView**).

 

![Diagrama: las clases KeysView, ValuesView e ItemsView heredan de MappingView y se obtienen con keys(), values() e items()](https://jarroba.com/wp-content/uploads/2019/04/Clases-bases-de-Vistas-de-MappingView-www.jarroba.com_.png)

 

Aunque las posibilidades con las Vistas (Views) son un poco más completas como veremos (más abajo dibujo un diagrama completo sobre las vistas; no lo he puesto aquí pues tiene unas cuantas flechas que de primera impresión pueden sorprender y, sin embargo, es bastante sencillo, quiero que sientas por ti mismo el porqué de las cosas y que es sencillo de entender).

 

 

## Son Medibles (Sized)

 

Es decir, **podremos utilizar “len()”** para cada una de las Vistas, lo que nos devolverá la cantidad de elementos de su interior.

 

Por ejemplo, voy a querer la cantidad de claves de la “vista_claves” que es de tipo KeysView (funciona igual las otras dos vistas de tipo ValuesView y ItemsView):

 

```python
cantidad_de_claves = len(vista_claves)
print("Cantidad de claves: {}".format(cantidad_de_claves))
```

 

Muestra:

 

```text
Cantidad de claves: 3
```

 

 

## Son iterables (Iterable)

 

Las Vistas son **Iterables** pues podremos recorrer sus elementos en un **bucle FOR**.

 

Por ejemplo, podremos iterar por cada uno de los elementos de “vista_valores” (también utilizar cualquiera de las tres vistas):

 

```python
for valor in vista_valores:
    print('Valor de mi_diccionario: {}'.format(valor))
```

 

Nos imprime:

 

```text
Valor de mi_diccionario: Manzano
Valor de mi_diccionario: Vid
Valor de mi_diccionario: Peral
```

 

Ojo y cuidado, **las Vistas NO son Iteradores** (iterator); es decir, no se puede usar next() para recorrer elemento a elemento de la “vista”.

 

**Recordatorio sobre Iterable vs Iterador (Iterator)**: no hay que confundir “Iterable” que implementa __iter__ con “Iterador” que implementa __next__, ni tampoco con “Iterador-Iterable” que implementa ambos __iter__ y __next__; está explicado con detalle en el artículo sobre como crear nuestra propia colección [https://jarroba.com/nuestra-propia-coleccion-en-python](https://jarroba.com/nuestra-propia-coleccion-en-python/?preview=true&_thumbnail_id=42544)).

 

 

## Las vistas con claves son Conjuntos (Set)

 

Las “vistas” que tengan claves, es decir, las de tipo **KeysView y** **ItemsView son**Conjuntos (**Set**). Por lo que quiere decir que podremos realizar cualquier operación de conjuntos sobre ellas (y quiere decir que los diccionarios han ganado la habilidad directa de ser “casi” conjuntos).

 

Supongamos que tenemos un conjunto de claves variadas (que llamaré “conjunto_claves”), de las cuales algunas se repiten a las claves de nuestro diccionario, como:

 

```python
conjunto_claves = {"MANZANA", "PERA", "TOMATE"}
```

 

Queremos saber qué claves se repiten tanto en la “vista_claves” como en “conjunto_claves” a la vez (A ojo puedes ver que se repiten “MANZANA” y “PERA”). Aplicando la operación de conjuntos de “intersección” (cuyo símbolo es “&”) nos da ese resultado que queremos al devolver las claves comunes de ambos:

 

```python
conjunto_claves_comunes = vista_claves & conjunto_claves
print('Conjunto de claves en ambos: {}'.format(conjunto_claves_comunes))
```

 

Y comprobamos por la consola como correctamente nos devuelve:

 

```text
Conjunto de claves en ambos: {'MANZANA', 'PERA'}
```

 

Funciona igual con la vista de Ítems. Podemos crear un conjunto de tuplas, y cada tupla tendrá la clave y el valor. Un ejemplo, querremos que nos devuelva los elementos que no coincidan en los dos (es decir, queremos los elementos únicos de cada conjunto, los no repetidos en conjunto_tuplas_clave_y_valor y en vista_items); para ello nos es útil el operador sobre conjuntos de “diferencia simétrica” (cuyo símbolo es “^”):

 

```python
conjunto_tuplas_clave_y_valor = {("MANZANA", "Manzano"), ("TOMATE", "Tomatero")}

conjunto_items_comunes = vista_items ^ conjunto_tuplas_clave_y_valor
print('Conjunto de ítems NO en ambos: {}'.format(conjunto_items_comunes))
```

 

Comprobamos que devuelve la consola un conjunto que no incluye a la tupla («MANZANA», «Manzano»), pues es la que se repite en ambos:

 

```text
Conjunto de ítems NO en ambos: {('PERA', 'Peral'), ('LIMÓN', 'Limonero'), ('TOMATE', 'Tomatero'), ('UVA', 'Vid')}
```

 

Aunque aquí solo he utilizado las operaciones de “intersección” (&) y de “diferencia simétrica” (^), realmente las Vistas **KeysView y ItemsView admiten cualquier operación sobre los conjuntos** (todas las operaciones de conjuntos se pueden encontrar en [https://docs.python.org/3.7/library/stdtypes.html#set](https://docs.python.org/3.7/library/stdtypes.html#set)).

 

**ValuesView NO es de tipo** Conjunto (**Set**), **pero sí de tipo** Colección (**Collection**). No es tipo Conjunto (Set) por el comportamiento de Tabla Hash de los diccionarios (más información de tablas hash en [https://jarroba.com/tablas-hash-o-tabla-de-dispersion/](https://jarroba.com/tablas-hash-o-tabla-de-dispersion/)), pues las claves son las únicas apuntadas directamente (es lo mismo que le ocurre a los conjuntos simples de Python) y los valores no.

 

Aunque ValuesView no puede trabajar con conjuntos directamente, se puede convertir esta Vista a un conjunto y operar igualmente (este truco no es tan óptimo, ya que se tienen que recorrer todos los valores para crear el conjunto; por lo que cuidado si trabajas con ingentes cantidades de datos, puede que tengas que replantear las estructuras de datos).

 

```python
conjunto_valores = {"Tomatero", "Vid", "Manzano"}

# Convertimos la vista en conjunto
conjunto_de_vista_valores = set(vista_valores)

conjunto_valores_comunes = conjunto_de_vista_valores & conjunto_valores
print('Conjunto de valores comunes: {}'.format(conjunto_valores_comunes))
```

 

Y al ejecutarlo vemos por pantalla que funciona:

 

```text
Conjunto de valores comunes: {'Vid', 'Manzano'}
```

 

 

## Clases de las Vistas (Views) extendidas

 

He aquí el diagrama de clases con todo lo que hemos aprendido hasta ahora (tanto en este artículo como en el anterior de crear nuestra propia colección [https://jarroba.com/nuestra-propia-coleccion-en-python/](https://jarroba.com/nuestra-propia-coleccion-en-python/) ):

 

![Diagrama de clases de las vistas y su relación con Set, Collection, Iterable, Container y Sized](https://jarroba.com/wp-content/uploads/2019/04/Clases-de-Vistas-de-MappingView-www.jarroba.com_.png-1024x540.png)

 

 

## Las vistas están asociadas a su diccionario

 

Como dijimos al principio del artículo: la principal cualidad de las **Vistas** es que **si modificamos algo de su diccionario asociado** (algún valor o clave), **se reflejará** en el interior de **las vistas**.

 

Comprobémoslo, obtengamos una de las vistas de nuestro diccionario, por ejemplo la vista de claves (con keys() obtenemos el objeto KeysView que se guardará en la variable “vista_claves”). Recorreremos la vista, modificaremos el diccionario, y volveremos a recorrer la vista para observar el cambio de las claves dentro de la vista (fíjate que la vista la obtenemos una única vez al principio del código):

 

```python
# Obtenemos una vista; por ejemplo, las claves
vista_claves = mi_diccionario.keys()

# Recorremos las claves de dentro de la vista
for clave in vista_claves:
    print('Clave de mi_diccionario ANTES: {}'.format(clave))

# Añadimos una clave y un valor que no exista en el diccionario
mi_diccionario["LIMÓN"] = "Limonero"

# Volvemos a recorrer las claves dentro de la vista para comprobar
for clave in vista_claves:
    print('Clave de mi_diccionario DESPUES: {}'.format(clave))
```

 

Podemos comprobar como la primera vez que recorremos las vista nos devuelve unas claves (en la siguiente salida de consola aparece con el texto “ANTES”); modificamos el diccionario, volvemos a recorrer la vista para comprobar cómo la vista también ha sido afectada:

 

```text
Clave de mi_diccionario ANTES: MANZANA
Clave de mi_diccionario ANTES: UVA
Clave de mi_diccionario ANTES: PERA

Clave de mi_diccionario DESPUES: MANZANA
Clave de mi_diccionario DESPUES: UVA
Clave de mi_diccionario DESPUES: PERA
Clave de mi_diccionario DESPUES: LIMÓN
```

 

 

## Ciclo de vida de los métodos de las Vistas (Views) de un Mapeo (Mapping)

 

Si queremos entender al completo el funcionamiento de las Vistas y sobre todo si queremos construir nuestras propias clases de Mapeo (Mapping), será necesario conocer el ciclo de vida de las Vistas (evidentemente será necesario conocer esto siempre que queramos modificar su comportamiento).

 

El ciclo de la vida para obtener las claves ya lo hemos visto, aunque aquí profundizo un poco más, pues podrás ver que devuelve cada uno de los objetos de las Vistas (KeysView, ValuesView e ItemsView):

 

![Esquema de cómo keys(), values() e items() de un Mapping devuelven KeysView, ValuesView e ItemsView](https://jarroba.com/wp-content/uploads/2019/04/Ciclo-de-vida-para-la-obtención-de-vistas-en-un-Mapping-de-Python-www.Jarroba.com_-1024x278.png)

 

Y dependiendo del uso que le demos a cada una de las Vistas llamará a una cosa u a otra. Los ciclos de vida explicados en la siguiente imagen son:

 
- **IF…IN** **llama** al método mágico **a __contains__**. Como vimos en el artículo de como hacer “Nuestra propia colección en Python” ([https://jarroba.com/nuestra-propia-coleccion-en-python](https://jarroba.com/nuestra-propia-coleccion-en-python)), con
- **Al iterar** (en un bucle FOR) por la vista de **KeysView llamará a __iter__**, pero al iterar por las vistas **ValuesView e ItemsView también llamará a __iter__** que obtiene las claves **y tiene que llamar por cada clave a __getitem__ para obtener su valor**.
- Al obtener el String de una Vista con **str()**, la vista **llamará a __repr__** que será la encargada de mostrar la representación de dicha vista.

 

![Esquema de los métodos de Mapping que invocan in, for y str() sobre las vistas: __contains__, __iter__, __getitem__ y __repr__](https://jarroba.com/wp-content/uploads/2019/04/Ciclo-de-vida-de-cada-método-usado-en-cada-vistas-en-un-Mapping-de-Python-www.Jarroba.com_-1-1024x657.png)

 

Veamos un ejemplo con nuestro propio Mapeo (Mapping) para entender cada uno de estos ciclos de vida.

 

 

## Trabajar con Vistas en nuestro propio Mapeo (Mapping)

 

Para este ejemplo voy a querer un Mapeo (Mapping) que dado un número en centenas como clave (100, 200, 300), me devuelva como valor su texto (“CIEN”, “DOSCIENTOS”, “TRESCIENTOS”).

 

Pasos que haré en el código (recomiendo ojear el código que está a continuación por cada punto leído):

 
1. En el siguiente código heredaré de Mapping porque solo quiero leer de mi diccionario personalizado (de mi objeto de tipo Mapping).
2. Utilizaré dos listados para guardar en uno las claves y en otros los valores; así por ejemplo, la posición 2 en el listado de claves (lista_interna_claves) será 300 y corresponderá con la posición 2 de su valor que será “TRESCIENTOS” en el listado de valores (lista_interna_valores).
3. Implementaré __len__ con un valor fijo, pues no puedo modificar el tamaño de mi diccionario de manera dinámica, y si en un futuro quiero llamar a len() me devolverá su tamaño.
4. __iter__ tiene que devolver un “Iterador” y en una clase de tipo Mapping tiene que devolver obligatoriamente las claves. Por lo que quiero devolver el listado “lista_interna_claves” pero listado el “Iterable” no “Iterador”, por lo que podemos utilizar el método iter() para devolver su “Iterador”.

 

```python
from collections import abc

class MiColeccionConVistas(abc.Mapping):

    def __init__(self, *args, **kwargs):
        self.lista_interna_claves = [100, 200, 300]
        self.lista_interna_valores = ["CIEN", "DOSCIENTOS", "TRESCIENTOS"]

    def __len__(self) -> int:
        return 3

    def __iter__(self):
        return iter(self.lista_interna_claves)

    def __getitem__(self, numero: int) -> str:
        try:
            posicion = self.lista_interna_claves.index(numero)
            return self.lista_interna_valores[posicion]
        except ValueError:
            raise KeyError
```

 

Unas pruebas básicas rápidas para nuestro anterior código serían:

 

```python
mi_coleccion_con_vistas = MiColeccionConVistas()

print('300 se escribe "{}"'.format(mi_coleccion_con_vistas[300]))

print('mi_coleccion_con_vistas tiene {} elementos'.format(len(mi_coleccion_con_vistas)))

if 200 in mi_coleccion_con_vistas:
    print('200 existe en mi_coleccion_con_vistas')
else:
    print('200 NO existe en mi_coleccion_con_vistas')

for valor in mi_coleccion_con_vistas:
    print('Elemento de mi_coleccion_con_vistas: {}'.format(valor))
```

 

Y veríamos por consola:

 

```text
300 se escribe "TRESCIENTOS"

mi_coleccion_con_vistas tiene 3 elementos

200 existe en mi_coleccion_con_vistas

Elemento de mi_coleccion_con_vistas: 100
Elemento de mi_coleccion_con_vistas: 200
Elemento de mi_coleccion_con_vistas: 300
```

 

Si hemos cumplido con la forma correcta de crear un Mapping no deberíamos tener ningún problema en poder obtener las Vistas (keys() para obtener KeysView, values() para obtener ValuesView e items() para obtener ItemsView), pues ya están implementadas en Mapping:

 

```python
vista_claves = mi_coleccion_con_vistas.keys()
print("vista_claves: {}".format(vista_claves))
for clave in vista_claves:
    print('Clave de mi_coleccion_con_vistas: {}'.format(clave))

vista_valores = mi_coleccion_con_vistas.values()
print("vista_valores: {}".format(vista_valores))
for valor in vista_valores:
    print('Valor de mi_coleccion_con_vistas: {}'.format(valor))

vista_items = mi_coleccion_con_vistas.items()
print("vista_items: {}".format(vista_items))
for item in vista_items:
    print('Ítem de mi_coleccion_con_vistas: {}'.format(item))
```

 

Podemos ver que nos imprime para cada Vista:

 

```text
vista_claves: KeysView(<__main__.MiColeccionConVistas object at 0x000001F8E406E9E8>)
Clave de mi_coleccion_con_vistas: 100
Clave de mi_coleccion_con_vistas: 200
Clave de mi_coleccion_con_vistas: 300

vista_valores: ValuesView(<__main__.MiColeccionConVistas object at 0x000001A8D106BBE8>)
Valor de mi_coleccion_con_vistas: CIEN
Valor de mi_coleccion_con_vistas: DOSCIENTOS
Valor de mi_coleccion_con_vistas: TRESCIENTOS

vista_items: ItemsView(<__main__.MiColeccionConVistas object at 0x000001F7D126B4E8>)
Ítem de mi_coleccion_con_vistas: (100, 'CIEN')
Ítem de mi_coleccion_con_vistas: (200, 'DOSCIENTOS')
Ítem de mi_coleccion_con_vistas: (300, 'TRESCIENTOS')
```

 

Realmente si quisiéramos implementar cada uno de los métodos que nos devuelve la vista tendríamos que implementar lo siguiente (hay que pasarle el Mapping, que sería “self”, a cada clase que construya cada una de las vistas para que obtenga la información que necesite, por ejemplo KeysView(self) ):

 

```python
class MiColeccionConVistas(abc.Mapping):

    # …

    def keys(self):
        return abc.KeysView(self)

    def values(self):
        return abc.ValuesView(self)

    def items(self):
        return abc.ItemsView(self)
```

 

Otro detalle que nos falta es la representación sobrescribiendo a __repr__; pues las Vistas lo usan para representarse con str(). Si no nos pasará lo que ha ocurrido antes, que nos devuelve el objeto con la posición de memoria:

 

```text
vista_claves: KeysView(<__main__.MiColeccionConVistas object at 0x000001F8E406E9E8>)
```

 

Queremos que nos dé información completa. Así que querremos ver un diccionario, por lo que tendremos que convertir dos listas a un diccionario; sabemos que el método de Python dict() si le pasamos un “Iterable” de tuplas (CLAVE, VALOR) nos creará un diccionario como lo queremos representar, y estas tuplas nos lo proporciona items(), por lo que podemos añadir a nuestra clase Mapping __repr__ (más información de __repr__ en [https://jarroba.com/repr-y-str-de-python/](https://jarroba.com/repr-y-str-de-python/)):

 

```python
class MiColeccionConVistas(abc.Mapping):

    # …

    def __repr__(self):
        dict_claves_y_valores = dict(self.items())
        return '{self.__class__.__name__}({dict_claves_y_valores})'.format(self=self, dict_claves_y_valores=dict_claves_y_valores)
```

 

Cuando se implementa __repr__ es muy recomendable modificar __init__ para que le lleguen los argumentos de __repr__ (ya que nos servirá para depurar y si no nos daría error nuestra herramienta de depuración). Por ejemplo “__init__(self, *args, **kwargs)”. En este ejemplo como es una clase Mapping que no admite mutabilidad (no se pueden añadir nuevos elementos), podría pensarse que no hace falta, pero es una buena costumbre modificar __init__ ya que casi siempre hace falta.

 

Por lo que nuestra clase entera quedará (no añado keys(), values() e items() pues no he aportado nada antes salvo lo que ya hacía por defecto):

 

```python
class MiColeccionConVistas(abc.Mapping):

    def __init__(self, *args, **kwargs):
        self.lista_interna_claves = [100, 200, 300]
        self.lista_interna_valores = ["CIEN", "DOSCIENTOS", "TRESCIENTOS"]

    def __len__(self) -> int:
        return 3

    def __iter__(self):
        return iter(self.lista_interna_claves)

    def __getitem__(self, numero: int) -> str:
        try:
            posicion = self.lista_interna_claves.index(numero)
            return self.lista_interna_valores[posicion]
        except ValueError:
            raise KeyError

    def __repr__(self):
        dict_claves_y_valores = dict(self.items())
        return '{self.__class__.__name__}({dict_claves_y_valores})'.format(self=self, dict_claves_y_valores=dict_claves_y_valores)
```

 

Ahora si imprimimos cada una de las vistas vemos que quedan bastante mejor:

 

```python
vista_claves = mi_coleccion_con_vistas.keys()
print("vista_claves: {}".format(vista_claves))

vista_valores = mi_coleccion_con_vistas.values()
print("vista_valores: {}".format(vista_valores))

vista_items = mi_coleccion_con_vistas.items()
print("vista_items: {}".format(vista_items))
```

 

Y nos muestra la representación como la queríamos:

 

```css
vista_claves: KeysView(MiColeccionConVistas({100: 'CIEN', 200: 'DOSCIENTOS', 300: 'TRESCIENTOS'}))

vista_valores: ValuesView(MiColeccionConVistas({100: 'CIEN', 200: 'DOSCIENTOS', 300: 'TRESCIENTOS'}))

vista_items: ItemsView(MiColeccionConVistas({100: 'CIEN', 200: 'DOSCIENTOS', 300: 'TRESCIENTOS'}))
```

 

 

## Convertir Vistas en listados

 

Es bastante sencillo convertir una vista en un listado con list().

 

```python
vista_claves = mi_coleccion_con_vistas.keys()
lista_claves = list(vista_claves)
```

 

Recuerda que la creación de un listado ocupará la memoria que necesite para llenarse, si es la última opción mejor.

 

 

## Bibliografía

 

- [Built-in Types (Python docs)](https://docs.python.org/3/library/stdtypes.html)
- [collections.abc — Abstract Base Classes for Containers (Python docs)](https://docs.python.org/3/library/collections.abc.html)
- [abc — Abstract Base Classes (Python docs)](https://docs.python.org/3/library/abc.html)
- [github.com/python/cpython/blob/master/Lib/_collections_abc.py](https://github.com/python/cpython/blob/master/Lib/_collections_abc.py)
- [github.com/python/cpython/blob/master/Lib/abc.py](https://github.com/python/cpython/blob/master/Lib/abc.py)
- [twitter.com/1st1/status/1064572563509121024](https://twitter.com/1st1/status/1064572563509121024)
- [docs.python.org/2/library/collections.html](https://docs.python.org/2/library/collections.html)
- [docs.python.org/2/library/stdtypes.html](https://docs.python.org/2/library/stdtypes.html)
