【问题标题】:Convert a namedtuple into a dictionary将命名元组转换为字典
【发布时间】:2014-11-28 14:31:41
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • btw...查看制表符完成或dir 命令,它将显示任何对象的字段...直接显示_asdict 函数。
  • 看起来你真正想要做的是dict的子类而不是'namedtuple',并将namedtuple传递给初始化程序。请记住,如果你习惯了 Cxx,class Town(x) 不是构造函数,def __init__(self, *args, **kwargs) 里面是。
  • 我无法将原始类更改为其他人代码中的类。所以我必须从 namedtouble 子类化
  • @CorleyBrigman 你能解释一下吗?我试图找到有关命名 touple 的文档,或者找到我可以调用它的内容,但我无法弄清楚如何。 (再次重申,python 不是我最擅长的语言)
  • 哪一部分? dir 只是一个 python 内置...你可以在 any python 对象、控制台或脚本中运行它(它返回一个列表,你可以打印或做任何事情) ,它将返回对象的(几乎)所有属性的列表。如果您想弄清楚未知对象的工作原理,这很有帮助。

标签: python dictionary tuples namedtuple


【解决方案1】:

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

这是一个命名元组的documented method,也就是说,与python中的通常约定不同方法名称的前导下划线不是不鼓励使用。除了添加到 namedtuples 的其他方法之外,_make_replace_source_fields,它具有下划线仅用于尝试防止与可能的字段名称发生冲突。


注意:对于一些 2.7.5

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

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

【讨论】:

  • 有谁知道是否有一个既定的先例表明 _asdict 不应在标准库中别名为 asdict
  • @KobeJohn 那么你不能让"asdict" 成为元组名称之一。
【解决方案2】:

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

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

【讨论】:

  • 我不是反对者,但这可能是因为 _asdict 方法一直是 obsoleted in python3 (in favour of vars)
  • 相反,vars 似乎不适用于某些旧版本 - 在 2.7 上,它会引发 TypeError,因为该版本的 namedtuple 类没有 __dict__ 属性。
  • 是的,Martijn 和我已经讨论过 here。它将适用于 2.7 btw 的较新版本(我在 2.7.6 上并且它有效)
  • 请注意:_asdict 不再被废弃(现在返回 OrderedDict),并且 vars 在 Python 3.4 中产生错误(从删除的 dict 属性命名元组)。
  • 我无法跟踪vars() 明显经常变化的状态。接受有关如何准确描述它的建议。
【解决方案3】:

在 python2.7 和 python3.4 的 Ubuntu 14.04 LTS 版本上,__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

看到 dict 是获取表示某物的字典的语义方式,(至少据我所知)。


如果能把主要的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     |

【讨论】:

  • Linux-3.10.0-693.el7.x86_64-x86_64-with-centos-7.4.1708-Core,Python 2.7 -- __dict__ 不起作用。
【解决方案4】:

通常_asdict() 返回OrderedDict。这是从OrderedDict 转换为常规dict 的方法


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

输出将是

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

【讨论】:

    【解决方案5】:

    案例#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()
    

    【讨论】:

      【解决方案6】:

      如果没有_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
      

      【讨论】:

        【解决方案7】:

        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}
        

        【讨论】:

        • 没有帮助,因为你知道名字在那里。应该是盲法
        猜你喜欢
        • 2011-04-03
        • 2013-04-01
        • 1970-01-01
        • 2011-12-11
        • 1970-01-01
        • 2014-09-19
        • 1970-01-01
        相关资源
        最近更新 更多