Convertir una tupla con nombre en un diccionario

7 minutos de lectura

avatar de usuario
Sin mí es simplemente increíble

Tengo una clase de tupla con nombre en python

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

Me gustaría convertir instancias de Town en diccionarios. No quiero que esté ligado rígidamente a los nombres o números de los campos en un Pueblo.

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

No puedo alterar la definición de clase original ya que está en el código de otra persona. Así que necesito tomar una instancia de Town y convertirla en un diccionario.

  • por cierto … mira la finalización de la pestaña o el dir comando, que le mostrará los campos para cualquier objeto… que habría mostrado el _asdict función directamente.

    –Corley Brigman

    3 oct 2014 a las 14:13

  • se parece a lo que tu De Verdad quiero hacer es una subclase de dict en lugar de ‘namedtuple’, y pase la namedtuple al inicializador. Recuerda que si estás acostumbrado a Cxx, class Town(x) no es el constructor, def __init__(self, *args, **kwargs) dentro está.

    –Corley Brigman

    3 oct 2014 a las 14:16

  • No puedo alterar la clase original ya que está en el código de otra persona. así que tengo que subclasificar de namedtouble

    – Sin mí es simplemente increíble

    3 oct 2014 a las 14:36

  • @CorleyBrigman, ¿puedes explicar esto más? Traté de encontrar documentación sobre el touple nombrado, o encontré lo que podía llamar y no pude averiguar cómo. (De nuevo, Python no es mi lenguaje más fuerte)

    – Sin mí es simplemente increíble

    06/10/2014 a las 20:04

  • ¿qué parte? dir es solo un python incorporado … puede ejecutarlo en ningún python, en una consola o en un script (donde devuelve una lista con la que puede imprimir o hacer lo que sea), y devolverá una lista de (casi) todos los atributos del objeto. útil si está tratando de averiguar cómo funciona un objeto desconocido.

    –Corley Brigman

    7 oct 2014 a las 13:49

avatar de usuario
ingenio

TL; DR: hay un método _asdict provisto 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')])

Esto es un método documentado de tuplas con nombre, es decir, a diferencia de la convención habitual en python el guión bajo inicial en el nombre del método no está allí para desalentar el uso. Junto con los otros métodos agregados a las tuplas con nombre, _make, _replace, _source, _fieldstiene el guión bajo solo para intentar evitar conflictos con posibles nombres de campo.


Nota: Para algunos códigos 2.7.5 < python version < 3.5.0 disponibles, es posible que vea esta versión:

>>> 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 estaba obsoleto (ver aquí), y sugirió usar el método incorporado vars. Ese consejo ahora está desactualizado; para arreglar un insecto relacionados con la subclasificación, la __dict__ propiedad que estaba presente en namedtuples ha sido nuevamente eliminada por este compromiso.

  • ¿Alguien sabe si hay un precedente establecido que sugiere _asdict no debe tener un alias en la biblioteca estándar para asdict?

    – Kobe John

    23 de mayo de 2016 a las 6:35

  • @KobeJohn, entonces no podrías haberlo hecho "asdict" ser uno de los nombres de tupla.

    – hablador de sombras

    16/10/2016 a las 16:14

avatar de usuario
Peter DeGlopper

Hay un método incorporado en namedtuple instancias 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 construcción, mientras que _asdict debe ser confiable. en algunas versiones _asdict se marcó como obsoleto, pero los comentarios indican que este ya no es el caso a partir de 3.4.

  • Yo no fui el votante negativo, pero podría ser porque el _asdict el método ha sido obsoleto en python3 (a favor de vars)

    – Wim

    3 oct 2014 a las 14:16

  • Por el contrario, parece vars no funciona en algunas versiones anteriores – en 2.7 plantea un TypeErrorya que esa versión es namedtuple la clase no tiene __dict__ atributo.

    -Peter DeGlopper

    3 oct 2014 a las 14:17


  • sí, Martijn y yo lo hemos discutido aquí. Funcionará en versiones más nuevas de 2.7 por cierto (estoy en 2.7.6 y funciona)

    – Wim

    3 oct 2014 a las 14:18


  • Solo un aviso: _asdict ya no está obsoleto (y devuelve un OrderedDict ahora), y vars produce un error con Python 3.4 (desde la eliminación del dictar atributo de tuplas nombradas).

    – Alexander Huszag

    21 de noviembre de 2015 a las 13:39

  • No puedo hacer un seguimiento del estado aparentemente cambiante de vars(). Abierto a sugerencias sobre cómo describirlo con precisión.

    -Peter DeGlopper

    9 de diciembre de 2015 a las 1:33

Normalmente _asdict() devuelve un OrderedDict. esta es la forma de convertir de OrderedDict a un habitual dict


town = Town('funky', 300, 'somewhere', 'lipps', 'chicken')
dict(town._asdict())

la salida será

{'capital': 'lipps',
 'coordinates': 'somewhere',
 'name': 'funky',
 'population': 300,
 'state_bird': 'chicken'}

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

$ pitón2.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 dictar 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 las principales versiones y plataformas de Python 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     |
| CentOS Linux release 7.4.1708 | Python2.7 | no       | yes     |
| CentOS Linux release 7.4.1708 | Python3.4 | no       | yes     |
| CentOS Linux release 7.4.1708 | Python3.6 | no       | yes     |

avatar de usuario
yongtaek junio

Caso #1: tupla de una dimensión

TUPLE_ROLES = (
    (912,"Role 21"),
    (913,"Role 22"),
    (925,"Role 23"),
    (918,"Role 24"),
)


TUPLE_ROLES[912]  #==> Error because it is out of bounce. 
TUPLE_ROLES[  2]  #==> will show Role 23.
DICT1_ROLE = {k:v for k, v in TUPLE_ROLES }
DICT1_ROLE[925] # will display "Role 23" 

Caso #2: tupla de dos dimensiones
Ejemplo: DICT_ROLES[961] # mostrará ‘Programador back-end’

NAMEDTUPLE_ROLES = (
    ('Company', ( 
            ( 111, 'Owner/CEO/President'), 
            ( 113, 'Manager'),
            ( 115, 'Receptionist'),
            ( 117, 'Marketer'),
            ( 119, 'Sales Person'),
            ( 121, 'Accountant'),
            ( 123, 'Director'),
            ( 125, 'Vice President'),
            ( 127, 'HR Specialist'),
            ( 141, 'System Operator'),
    )),
    ('Restaurant', ( 
            ( 211, 'Chef'), 
            ( 212, 'Waiter/Waitress'), 
    )),
    ('Oil Collector', ( 
            ( 211, 'Truck Driver'), 
            ( 213, 'Tank Installer'), 
            ( 217, 'Welder'),
            ( 218, 'In-house Handler'),
            ( 219, 'Dispatcher'),
    )),
    ('Information Technology', ( 
            ( 912, 'Server Administrator'),
            ( 914, 'Graphic Designer'),
            ( 916, 'Project Manager'),
            ( 918, 'Consultant'),
            ( 921, 'Business Logic Analyzer'),
            ( 923, 'Data Model Designer'),
            ( 951, 'Programmer'),
            ( 953, 'WEB Front-End Programmer'),
            ( 955, 'Android Programmer'),
            ( 957, 'iOS Programmer'),
            ( 961, 'Back-End Programmer'),
            ( 962, 'Fullstack Programmer'),
            ( 971, 'System Architect'),
    )),
)

#Thus, we need dictionary/set

T4 = {}
def main():
    for k, v in NAMEDTUPLE_ROLES:
        for k1, v1 in v:
            T4.update ( {k1:v1}  )
    print (T4[961]) # will display 'Back-End Programmer'
    # print (T4) # will display all list of dictionary

main()

avatar de usuario
Ebubekir Tabak

si no hay _asdict(), puede usar de esta manera:

def to_dict(model):
    new_dict = {}
    keys = model._fields
    index = 0
    for key in keys:
        new_dict[key] = model[index]
        index += 1

    return new_dict

avatar de usuario
André Odendaal

Python 3. Asigne 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}

  • No es útil ya que sabes que el nombre está ahí. debería ser un método ciego

    – Mitchell Currie

    18 de marzo de 2018 a las 2:26

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad