python Llamado tupla al diccionario


Tengo una clase de tupla con nombre en python

class Town(collections.namedtuple('Town', [
    'name', 
    'population',
    'coordinates',
    'population', 
    'capital', 
    'state_bird'])):
    # ...

Lo que me gustaría hacer es convertir esto en un diccionario. Admito que Python no es uno de mis lenguajes más fuertes. La clave es que no quiero que esté rígidamente atado al nombre o números de los campos que tengo.

Hay una manera de escribirlo de tal manera que pueda agregar más campos, o pasar una tupla con nombre completamente diferente y obtener un diccionario.

Edit: No puedo alterar la definición original de la clase ya que está en alguien elses codificar. Así que necesito tomar un ejemplo de una ciudad y convertirlo en un diccionario.

Author: Chris Martin, 2014-10-03

4 answers

TL; DR: hay un método _asdict proporcionado para esto.

Aquí hay una demostración del uso:

>>> fields = ['name', 'population', 'coordinates', 'capital', 'state_bird']
>>> Town = collections.namedtuple('Town', fields)
>>> funkytown = Town('funky', 300, 'somewhere', 'lipps', 'chicken')
>>> funkytown._asdict()
OrderedDict([('name', 'funky'),
             ('population', 300),
             ('coordinates', 'somewhere'),
             ('capital', 'lipps'),
             ('state_bird', 'chicken')])

Este es un método documentado de namedtuples, es decir, a diferencia de la convención habitual en python el subrayado inicial en el nombre del método no está ahí para desalentar el uso. Junto con los otros métodos añadidos a namedtuples, _make, _replace, _source, _fields, tiene el subrayado solo para tratar de prevenir conflictos con posible campo nombre.


Nota: Para algunos 2.7.5

>>> vars(funkytown)
OrderedDict([('name', 'funky'),
             ('population', 300),
             ('coordinates', 'somewhere'),
             ('capital', 'lipps'),
             ('state_bird', 'chicken')])

Durante un tiempo la documentación había mencionado que _asdict era obsoleto (ver aquí), y sugirió usar el método incorporado vars. Ese consejo ahora está desactualizado; para corregir un error relacionado con la subclase, la propiedad __dict__ que estaba presente en namedtuples ha sido eliminada nuevamente por este commit.

 156
Author: wim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-03 00:38:05

Hay un método incorporado en las instancias namedtuple para esto, _asdict.

Como se discutió en los comentarios, en algunas versiones vars() también lo hará, pero aparentemente depende en gran medida de los detalles de compilación, mientras que _asdict debería ser confiable. En algunas versiones _asdict fue marcado como obsoleto, pero los comentarios indican que este ya no es el caso a partir de 3.4.

 19
Author: Peter DeGlopper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-09 08:29:58

En las versiones Ubuntu 14.04 LTS de python2.7 y python3.4 la propiedad __dict__ funcionó como se esperaba. Las _asdict method también funcionó, pero me inclino a usar la api de propiedad uniforme definida por estándares en lugar de la api no uniforme localizada.

Pyth python2. 7

# Works on:
# Python 2.7.6 (default, Jun 22 2015, 17:58:13)  [GCC 4.8.2] on linux2
# Python 3.4.3 (default, Oct 14 2015, 20:28:29)  [GCC 4.8.4] on linux

import collections

Color = collections.namedtuple('Color', ['r', 'g', 'b'])
red = Color(r=256, g=0, b=0)

# Access the namedtuple as a dict
print(red.__dict__['r'])  # 256

# Drop the namedtuple only keeping the dict
red = red.__dict__
print(red['r'])  #256

Viendo como dict es la forma semántica de obtener un diccionario que represente algo, (al menos hasta donde yo sé).


Sería bueno acumular una tabla de python principal versiones y plataformas y su soporte para __dict__, actualmente solo tengo una versión de plataforma y dos versiones de python como se publicó anteriormente.

| Platform         | PyVer     | __dict__ | _asdict |
| -------------    | --------- | -------- | ------- |
| Ubuntu 14.04 LTS | Python2.7 | yes      | yes     |
| Ubuntu 14.04 LTS | Python3.4 | yes      | yes     |
 2
Author: ThorSummoner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-28 05:26:49

Python 3. Asignar cualquier campo al diccionario como el índice requerido para el diccionario, usé 'nombre'.

import collections

Town = collections.namedtuple("Town", "name population coordinates capital state_bird")

town_list = []

town_list.append(Town('Town 1', '10', '10.10', 'Capital 1', 'Turkey'))
town_list.append(Town('Town 2', '11', '11.11', 'Capital 2', 'Duck'))

town_dictionary = {t.name: t for t in town_list}
 -4
Author: Andre Odendaal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-06 19:52:56