240 Stimmen

Konvertieren Sie ein namedtuple in ein Dictionary

Ich habe eine benannte Tupelklasse in Python

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

Ich möchte Instanzen von Town in Wörterbücher konvertieren. Ich möchte nicht starr an die Namen oder Anzahl der Felder in einer Town gebunden sein.

Gibt es eine Möglichkeit, es so zu schreiben, dass ich weitere Felder hinzufügen oder ein völlig anderes benanntes Tupel übergeben und ein Wörterbuch erhalten könnte.

Da die ursprüngliche Klassendefinition in jemand anderem Code liegt, kann ich sie nicht ändern. Daher muss ich eine Instanz einer Town nehmen und in ein Wörterbuch konvertieren.

416voto

wim Punkte 297608

_TL;DR: es gibt eine Methode _asdict, die dafür bereitgestellt wird._

Hier ist eine Demonstration der Verwendung:

>>> from collections import namedtuple
>>> fields = ['name', 'population', 'coordinates', 'capital', 'state_bird']
>>> Town = namedtuple('Town', fields)
>>> funkytown = Town('funky', 300, 'irgendwo', 'lipps', 'huhn')
>>> funkytown._asdict()
{'name': 'funky',
 'population': 300,
 'coordinates': 'irgendwo',
 'capital': 'lipps',
 'state_bird': 'huhn'}

Dies ist eine dokumentierte Methode von benannten Tupeln, d.h. im Gegensatz zur üblichen Konvention in Python ist der führende Unterstrich im Methodennamen nicht dazu da, die Verwendung abzuraten. Neben den anderen Methoden, die den benannten Tupeln hinzugefügt wurden, _make, _replace, _source, _fields, hat der Unterstrich nur den Zweck, Konflikte mit möglichen Feldnamen zu vermeiden.


Hinweis: Für einige 2.7.5 < Python-Version < 3.5.0 Code, der da draußen ist, könnte man diese Version sehen:

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

In der Dokumentation wurde eine Zeit lang erwähnt, dass _asdict veraltet war (siehe hier) und vorgeschlagen wurde, die integrierte Methode vars zu verwenden. Dieser Ratschlag ist jetzt veraltet; um einen Fehler im Zusammenhang mit der Unterklasse zu beheben, wurde das __dict__-Eigenschaft, das auf benannten Tupeln vorhanden war, erneut durch diesen Commit entfernt.

35voto

Peter DeGlopper Punkte 36286

Es gibt eine integrierte Methode auf namedtuple-Instanzen dafür, _asdict.

Wie in den Kommentaren diskutiert, funktioniert es in einigen Versionen auch mit vars(), aber das ist anscheinend stark abhängig von den Build-Details, während _asdict zuverlässig sein sollte. In einigen Versionen wurde _asdict als veraltet markiert, aber Kommentare deuten darauf hin, dass dies seit 3.4 nicht mehr der Fall ist.

9voto

simone Punkte 459

Normalerweise gibt _asdict() ein OrderedDict zurück. So konvertieren Sie von OrderedDict zu einem normalen dict:

stadt = Stadt('funky', 300, 'irgendwo', 'lipps', 'huhn')
dict(stadt._asdict())

die Ausgabe wird sein

{'hauptstadt': 'lipps',
 'koordinaten': 'irgendwo',
 'name': 'funky',
 'bevölkerung': 300,
 'staatsvogel': 'huhn'}

3voto

ThorSummoner Punkte 13974

Bei den Ubuntu 14.04 LTS-Versionen von python2.7 und python3.4 hat die __dict__-Eigenschaft wie erwartet funktioniert. Die _asdict Methode hat auch funktioniert, aber ich neige dazu, die standardsdefinierte, einheitliche Property-API anstelle der lokalen, nicht einheitlichen API zu verwenden.

$ python2.7

# Funktionierte auf:
# Python 2.7.6 (Standard, 22. Juni 2015, 17:58:13)  [GCC 4.8.2] unter linux2
# Python 3.4.3 (Standard, 14. Oktober 2015, 20:28:29)  [GCC 4.8.4] unter linux

import collections

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

# Greifen Sie auf das namedtuple als ein Dict zu
print(rot.__dict__['r'])  # 256

# Das namedtuple verwerfen und nur das Dict behalten
rot = rot.__dict__
print(rot['r'])  #256

Da dict der semantische Weg ist, um eine etwas darstellende Diktatur zu erhalten, (zumindest nach bestem Wissen).


Es wäre schön, eine Tabelle der wichtigsten Python-Versionen und Plattformen zu akkumulieren und deren Unterstützung für __dict__ zu erhalten, derzeit habe ich nur eine Plattformversion und zwei Python-Versionen wie oben gepostet.

| Plattform                      | PyVer     | __dict__ | _asdict |
| --------------------------    | --------- | -------- | ------- |
| Ubuntu 14.04 LTS              | Python2.7 | ja       | ja      |
| Ubuntu 14.04 LTS              | Python3.4 | ja       | ja      |
| CentOS Linux Release 7.4.1708 | Python2.7 | nein     | ja      |
| CentOS Linux Release 7.4.1708 | Python3.4 | nein     | ja      |
| CentOS Linux Release 7.4.1708 | Python3.6 | nein     | ja      |

-1voto

yongtaek jun Punkte 135

Case #1: ein dimensionales Tupel

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

TUPLE_ROLES[912]  #==> Fehler, weil es außerhalb des Bereichs liegt.
TUPLE_ROLES[  2]  #==> wird Rolle 23 anzeigen.
DICT1_ROLE = {k:v for k, v in TUPLE_ROLES }
DICT1_ROLE[925] # wird "Rolle 23" anzeigen

Case #2: zweidimensionales Tupel
Beispiel: DICT_ROLES[961] # wird 'Back-End Programmierer' anzeigen

NAMEDTUPLE_ROLES = (
    ('Firma', ( 
            ( 111, 'Besitzer/Geschäftsführer/Präsident'), 
            ( 113, 'Manager'),
            ( 115, 'Empfangsdame'),
            ( 117, 'Vermarkter'),
            ( 119, 'Verkäufer'),
            ( 121, 'Buchhalter'),
            ( 123, 'Direktor'),
            ( 125, 'Vizepräsident'),
            ( 127, 'HR-Spezialist'),
            ( 141, 'Systembetreiber'),
    )),
    ('Restaurant', ( 
            ( 211, 'Koch'), 
            ( 212, 'Kellner/Kellnerin'), 
    )),
    ('Ölsammler', ( 
            ( 211, 'LKW-Fahrer'), 
            ( 213, 'Tankinstallateur'), 
            ( 217, 'Schweißer'),
            ( 218, 'Hausinterner Handler'),
            ( 219, 'Disponent'),
    )),
    ('Informationstechnologie', ( 
            ( 912, 'Serveradministrator'),
            ( 914, 'Grafikdesigner'),
            ( 916, 'Projektmanager'),
            ( 918, 'Berater'),
            ( 921, 'Business-Logik-Analysator'),
            ( 923, 'Datenmodell-Designer'),
            ( 951, 'Programmierer'),
            ( 953, 'WEB-Front-End-Programmierer'),
            ( 955, 'Android-Programmierer'),
            ( 957, 'iOS-Programmierer'),
            ( 961, 'Back-End Programmierer'),
            ( 962, 'Fullstack-Programmierer'),
            ( 971, 'Systemarchitekt'),
    )),
)

#Deshalb benötigen wir ein Wörterbuch/Set

T4 = {}
def main():
    for k, v in NAMEDTUPLE_ROLES:
        for k1, v1 in v:
            T4.update ( {k1:v1}  )
    print (T4[961]) # wird 'Back-End Programmierer' anzeigen
    # print (T4) # wird die gesamte Liste des Wörterbuchs anzeigen

main()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X