【问题标题】:Multiple assignments into a python dictionarypython字典中的多个赋值
【发布时间】:2014-02-08 22:39:48
【问题描述】:

是否可以以比下面的更简洁的方式为字典的多个键分配值?

我的意思是,让d 是一个字典,初始化如下:

d={'a':1,'b':2,'c':3}

要将值分配给多个键,我需要这样做:

d['a']=10
d['b']=200
d['c']=30

我能用这样的东西达到同样的效果吗:

d['a','b','c']=10,200,30

谢谢。

【问题讨论】:

    标签: python dictionary


    【解决方案1】:

    你可以使用dict.update:

    d.update({'a': 10, 'c': 200, 'c': 30})
    

    这将覆盖现有键的值并为不存在的键添加新的键值对。

    【讨论】:

    • 是的,这确实有效。我知道update(),但是...谢谢。
    • 您也可以将其写为d.update(a=10, b=200, c=300),只要键是有效的标识符(就像在构造函数中一样)。
    • 有一个更快的方法:d = {**d, **dict(zip(keys, values))}。详情见我的评论:stackoverflow.com/a/45043651/618045
    • @WiseStrawberry。为什么?这是合法的 Python 语法 (Python >=3.5)。
    • 并不是说它不合法的python语法,它只是不太可读,我认为它很优雅,但不可读。只是我的2美分。在 python 中,可读代码通常比复杂代码更受欢迎。
    【解决方案2】:

    您也可以简单地使用multiple assigment semantics

    d['a'], d['b'], d['c'] = 10, 200, 30
    

    【讨论】:

    • 最优雅的解决方案
    【解决方案3】:

    你总是可以将它包装在一个函数中:

    def multiassign(d, keys, values):
        d.update(zip(keys, values))
    

    即使你不知道update,你也可以这样写:

    def multiassign(d, keys, values):
        for k, v in zip(keys, values):
            d[k] = v
    

    或者您甚至可以编写一个dict 子类,为您提供所需的语法:

    class EasyDict(dict):
        def __getitem__(self, key):
            if isinstance(key, tuple):
                return [super().__getitem__(k) for k in key]
            else:
                return super().__getitem__(key)
        def __setitem__(self, key, value):
            if isinstance(key, tuple):
                self.update(zip(key, value))
            else:
                super().__setitem__(key, value)
        def __delitem__(self, key, value):
            if isinstance(key, tuple):
                for k in key: super().__delitem__(k)
            else:
                super().__setitem__(key, value)
    

    现在:

    >>> d = {'a': 1, 'd': 4}
    >>> multiassign(d, ['a', 'b', 'c'], [10, 200, 300])
    >>> d
    {'a': 10, 'b': 200, 'c': 300, 'd': 4}
    >>> d2 = EasyDict({'a': 1, 'd': 4})
    >>> d2['a', 'b', 'c'] = 100, 200, 300
    >>> d2
    {'a': 10, 'b': 200, 'c': 300, 'd': 4}
    

    请注意,显然不再可以将元组用作 EasyDict 中的键。

    另外,如果您打算将它用于严重的事情,您可能想要改进错误处理。 (d['a', 'b'] = 1 会给出一个关于zip argument #2 must support iteration 的神秘信息,d['a', 'b', 'c'] = 1, 2 会默默地工作,对c 什么都不做,等等)

    【讨论】:

      【解决方案4】:

      速度比较,从最差到最好:

      Python 3.5.3 |Continuum Analytics, Inc.| (default, May 15 2017, 10:43:23) [MSC v.1900 64 bit (AMD64)]
      Type 'copyright', 'credits' or 'license' for more information
      IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.
      
      In [1]: import numpy.random as nprnd
         ...: d = dict([(_, nprnd.rand()) for _ in range(1000)])
         ...: values = nprnd.randint(1000, size=10000)
         ...: keys = nprnd.randint(1000, size=10000)
         ...: def multiassign(d, keys, values):
         ...:     for k, v in zip(keys, values):
         ...:         d[k] = v
         ...:
         ...: d1 = dict(d)
         ...: %timeit multiassign(d1, keys, values)
         ...: d1 = dict(d)
         ...: %timeit {**d1, **{keys[i]: values[i] for i in range(len(keys))}}
         ...: d1 = dict(d)
         ...: %timeit d1.update(zip(keys, values))
         ...: d1 = dict(d)
         ...: %timeit {*d1.items(), *zip(keys, values)}
         ...: d1 = dict(d)
         ...: %timeit {**d1, **{key: value for key, value in zip(keys, values)}}
         ...: d1 = dict(d)
         ...: %timeit {**d1, **dict(zip(keys, values))}
      4 ms ± 25.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      3.66 ms ± 29.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      3.17 ms ± 31.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      2.81 ms ± 98.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      2.38 ms ± 75.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
      1.96 ms ± 21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
      

      所以明显的赢家是从字典中重新创建字典。

      【讨论】:

        【解决方案5】:

        您可以使用字典理解,例如

        letters, nos = ['a','b','c'], [1,2,3]
        d = {letters[i]: nos[i] for i in range(len(nos))}
        

        输出:

        {'a': 1, 'c': 3, 'b': 2}

        【讨论】:

        • 使用这种格式的数据,dict(zip(letters, nos)) 会更整洁
        猜你喜欢
        • 2013-07-24
        • 1970-01-01
        • 1970-01-01
        • 2019-05-14
        • 1970-01-01
        • 2019-02-27
        • 2013-08-31
        • 2017-08-12
        • 2021-09-03
        相关资源
        最近更新 更多