Python 将命名元组转换为字典

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26180528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:11:13  来源:igfitidea点击:

Convert a namedtuple into a dictionary

pythondictionarytuplesnamedtuple

提问by Without Me It Just Aweso

I have a named tuple class in python

我在 python 中有一个命名的元组类

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

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.

我想将 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.

我无法像在其他人的代码中那样更改原始类定义。所以我需要获取一个城镇的实例并将其转换为字典。

采纳答案by wim

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

TL;DR:_asdict为此提供了一种方法。

Here is a demonstration of the usage:

下面是用法演示:

>>> 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')])

This is a documented methodof 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.

这是namedtuples的文档化方法,即与python 中的通常约定不同,方法名称上的前导下划线不是为了阻止使用。与添加到命名元组的其他方法一起,_make, _replace, _source, _fields,它具有下划线只是为了尝试和防止与可能的字段名称发生冲突。



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

注意:对于一些 2.7.5 < python version < 3.5.0 的代码,你可能会看到这个版本:

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

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

有一段时间,文档提到_asdict过时(请参阅此处),并建议使用内置方法vars。这个建议现在已经过时了。为了修复与子类化相关的错误__dict__此提交再次删除了namedtuples 上存在的属性。

回答by Peter DeGlopper

There's a built in method on namedtupleinstances for this, _asdict.

namedtuple实例中有一个内置方法,_asdict.

As discussed in the comments, on some versions vars()will also do it, but it's apparently highly dependent on build details, whereas _asdictshould be reliable. In some versions _asdictwas marked as deprecated, but comments indicate that this is no longer the case as of 3.4.

正如评论中所讨论的,在某些版本上vars()也会这样做,但它显然高度依赖于构建细节,而_asdict应该是可靠的。在某些版本中_asdict被标记为已弃用,但评论表明从 3.4 开始不再如此。

回答by ThorSummoner

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

在 Ubuntu 14.04 LTS 版本的 python2.7 和 python3.4 上,该__dict__属性按预期工作。该_asdict方法也有效,但我倾向于使用标准定义的、统一的、属性 api 而不是本地化的非统一 api。

$ python2.7

$ 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 dictis the semantic way to get a dictionary representing soemthing, (at least to the best of my knowledge).

dict视为获取表示某些事物的字典的语义方式(至少据我所知)。



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.

最好能积累一张主要的 Python 版本和平台以及它们对__dict__.

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

回答by Andre Odendaal

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

Python 3. 将任何字段分配给字典作为字典的必需索引,我使用了'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}

回答by yongtaek jun

Case #1: one dimension tuple

案例#1:一维元组

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" 

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

案例#2:二维元组
示例:DICT_ROLES[961] # 将显示“后端程序员”

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

回答by Ebubekir Tabak

if no _asdict(), you can use this way:

如果没有_asdict(),你可以这样使用:

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