将namedtuple转换成字典


147

我在python中有一个命名的tuple类

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

我想将Town实例转换成字典。我不希望它与城镇中字段的名称或数量严格相关。

有没有一种方法可以编写它,以便我可以添加更多字段,或者传入完全不同的命名元组并获得字典。

我无法更改其他人代码中的原始类定义。因此,我需要以一个Town实例为例,并将其转换为字典。


2
顺便说一句...查看制表符补全或dir命令,它将为您显示任何对象的字段... _asdict直接显示该功能。
Corley Brigman,2014年

看起来您真正想要做的是从而dict不是'namedtuple'的子类,然后将namedtuple传递给初始化程序。请记住,如果您习惯使用Cxx,class Town(x)它不是构造函数,def __init__(self, *args, **kwargs)而是内部构造函数。
Corley Brigman 2014年

我无法更改其他人代码中的原始类。所以我必须从namedtouble继承一个类
没有我,只是Aweso 2014年

@CorleyBrigman您能解释更多吗?我试图找到有关命名的touple的文档,或者找到我可以调用的文档,但我不知道该怎么做。(再次,python不是我最强的语言)
没有我,只是Aweso 2014年

2
哪一部分?dir只是内置的python ...您可以在控制台或脚本中的任何 python对象上运行它(它返回可以打印或执行任何操作的列表),并且将返回(几乎)列表)所有对象的属性。如果您想弄清楚未知对象是如何工作的,这将很有帮助。
Corley Brigman 2014年

Answers:


267

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

这是用法的演示:

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

这是一个已记录的namedtuples 方法,即,与python中的常规约定不同,该方法名上的前划线并不妨碍使用。随着加入namedtuples其他方法,_make_replace_source_fields,它有下划线只尝试和防止可能的字段名的冲突。


注意: 对于一些2.7.5 <python版本<3.5.0的代码,您可能会看到以下版本:

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

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


1
有谁知道_asdict标准库中asdict是否存在别名不应被别名的建议?
科比·约翰'16

1
@KobeJohn,那么您就不能"asdict"成为元组名称之一。
Shadowtalker '16

28

namedtuple实例上有一个内置方法_asdict

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


1
我不是拒绝投票的人,但这可能是因为该_asdict方法已在python3中作废(支持vars)
2014年

相反,它似乎vars在某些旧版本上不起作用-在2.7上它引发了TypeError,因为该版本的namedtuple类没有__dict__属性。
Peter DeGlopper 2014年

是的,马丁和我在这里讨论。它将在2.7 btw的较新版本上运行(我在2.7.6上运行)
2014年

经过我上面的评论中的编辑窗口-在2.7.5上失败,因此它必须是自2.7.6起的新版本。除非我的2.7.5版本已关闭,否则像Martijn的链接所示?无论如何,它是否适用于2.7.5似乎取决于构建细节。
Peter DeGlopper 2014年

8
请注意:_asdict不再被废弃(现在返回OrderedDict),并且vars使用Python 3.4产生错误(从namedtuples的dict属性的移除)。
Alexander Huszagh

2

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

视为字典是获取表示词义的字典的语义方式(至少据我所知)。


汇总主要python版本和平台及其对它们的支持会很高兴__dict__,目前如上所述,我只有一个平台版本和两个python版本。

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

1
Linux-3.10.0-693.el7.x86_64-x86_64-with-centos-7.4.1708-Core,Python 2.7- __dict__不起作用。
gbtimmon

-1

案例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" 

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


-5

Python 3.将任何字段分配给字典作为字典的必需索引,我使用了“名称”。

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}

因为您知道那里的名字,所以没有帮助。它应该是一种盲目的方法
Mitchell Currie
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.