添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'd like to convert Town instances into dictionaries. I don't want it to be rigidly tied to the names or number of the fields in a Town.

Is there a way to write it such that I could add more fields, or pass an entirely different named tuple in and get a dictionary.

I can not alter the original class definition as its in someone else's code. So I need to take an instance of a Town and convert it to a dictionary.

btw... look at tab completion or the dir command, which will show you the fields for any object... that would have shown the _asdict function directly. Corley Brigman Oct 3, 2014 at 14:13 it looks like what you really want to do is subclass from dict instead of 'namedtuple', and pass the namedtuple into the initializer. Remember that if you're used to Cxx, class Town(x) isn't the constructor, def __init__(self, *args, **kwargs) inside it is. Corley Brigman Oct 3, 2014 at 14:16 I can not alter the original class as its in someone elses code. so I have to subclass from namedtouble Without Me It Just Aweso Oct 3, 2014 at 14:36 @CorleyBrigman can you explain this more? I tried to find documentation on the named touple, or find what I could call on it and I couldnt figure out how. (Again python is not my strongest language) Without Me It Just Aweso Oct 6, 2014 at 20:04 which part? dir is just a python built-in... you can run it on any python object, in a console or in a script (where it returns a list you can print or do whatever with), and it will return a list of (nearly) all the attributes the object. helpful if you're trying to figure out how an unknown object works. Corley Brigman Oct 7, 2014 at 13:49

TL;DR: there's a method _asdict provided for this.

Here is a demonstration of the usage:

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

This is a documented method of namedtuples, i.e. unlike the usual convention in python the leading underscore on the method name isn't there to discourage use. Along with the other methods added to namedtuples, _make, _replace, _source, _fields, it has the underscore only to try and prevent conflicts with possible field names.

Note: For some 2.7.5 < python version < 3.5.0 code out in the wild, you might see this version:

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

For a while the documentation had mentioned that _asdict was obsolete (see here), and suggested to use the built-in method vars. That advice is now outdated; in order to fix a bug related to subclassing, the __dict__ property which was present on namedtuples has again been removed by this commit.

Does anyone know if there an established precedent that suggests _asdict shouldn't be aliased in the standard library to asdict? – KobeJohn May 23, 2016 at 6:35 infuriating! vars is the natural, idiomatic way to do this! Could it not handle namedtuple as a special case? Doesn't seem to me like it would be tooo hard – robert Aug 3, 2022 at 17:20 @robert vars(obj) is supposed to be equivalent to obj.__dict__, so the special-case would be changing the documented behavior of vars (tuple instances don't carry around a __dict__) – wim Aug 3, 2022 at 18:23 yes, I understand the excuse, but it doesn't cut any ice with me. What you are describing is how it is implemented, and vars "hides" that implementation (to use the OO parlance). I guess there's probably a "good" reason why they couldn't simply overload the method, but to me it seems like a slip in standards. – robert Aug 3, 2022 at 18:25 I wasn't the downvoter, but it could be because the _asdict method has been obsoleted in python3 (in favour of vars) – wim Oct 3, 2014 at 14:16 Conversely, it looks like vars does't work on some older versions - on 2.7 it raises a TypeError, since that version's namedtuple class does not have an __dict__ attribute. – Peter DeGlopper Oct 3, 2014 at 14:17 yes, Martijn and I have discussed that here. It will work on newer versions of 2.7 btw (I'm on 2.7.6 and it works) – wim Oct 3, 2014 at 14:18 Just a heads up: _asdict is not longer obseleted (and returns an OrderedDict now), and vars produces an error with Python 3.4 (from the removal of the dict attribute of namedtuples). – Alex Huszagh Nov 21, 2015 at 13:39 I can't keep track of the apparently often-changing state of vars(). Open to suggestions for how else to accurately describe it. – Peter DeGlopper Dec 9, 2015 at 1:33

Normally _asdict() returns a OrderedDict. this is how to convert from OrderedDict to a regular dict

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

the output will be

{'capital': 'lipps',
 'coordinates': 'somewhere',
 'name': 'funky',
 'population': 300,
 'state_bird': 'chicken'}
                This is no longer necessary.  As of Python 3.8, _asdict() returns a dict and not an OrderedDict
– Marc Meketon
                Mar 5 at 18:47

On Ubuntu 14.04 LTS versions of python2.7 and python3.4 the __dict__ property worked as expected. The _asdict method also worked, but I'm inclined to use the standards-defined, uniform, property api instead of the localized non-uniform api.

$ 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

Seeing as dict is the semantic way to get a dictionary representing soemthing, (at least to the best of my knowledge).

It would be nice to accumulate a table of major python versions and platforms and their support for __dict__, currently I only have one platform version and two python versions as posted above.

| 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     |
                Linux-3.10.0-693.el7.x86_64-x86_64-with-centos-7.4.1708-Core, Python 2.7 -- __dict__ does not work.
– gbtimmon
                Dec 20, 2018 at 17:19
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" 

Case #2: Two dimension tuple
Example: DICT_ROLES[961] # will show 'Back-End Programmer'

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()

Python 3. Allocate any field to the dictionary as the required index for the dictionary, I used 'name'.

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}
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.