多个赋值到python字典中

ozi*_*ozi 34 python dictionary

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

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

d={'a':1,'b':2,'c':3}
Run Code Online (Sandbox Code Playgroud)

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

d['a']=10
d['b']=200
d['c']=30
Run Code Online (Sandbox Code Playgroud)

我可以用这样的东西实现同样的目标:

d['a','b','c']=10,200,30
Run Code Online (Sandbox Code Playgroud)

谢谢.

Aam*_*nan 58

你可以使用dict.update:

d.update({'a': 10, 'c': 200, 'c': 30})
Run Code Online (Sandbox Code Playgroud)

这将覆盖现有密钥的值,并为尚不存在的密钥添加新的键值对.

  • 您也可以将其写为`d.update(a = 10,b = 200,c = 300)`,只要这些键是有效的标识符(就像在构造函数中一样). (6认同)
  • 有一种更快的方法:d = {** d,** dict(zip(keys,values))}。请参阅我的评论以获取详细信息:/sf/answers/3153055601/ (2认同)
  • @WiseStrawberry。为什么?这是合法的 python 语法 (Python >=3.5)。 (2认同)
  • 并不是说它不合法的 python 语法,只是不太可读,我认为它很优雅,但不可读。只是我的2分钱。在 python 中,可读代码通常优于复杂代码。 (2认同)

Del*_*gan 10

您也可以简单地使用多重赋值语义

d['a'], d['b'], d['c'] = 10, 200, 30
Run Code Online (Sandbox Code Playgroud)


aba*_*ert 8

您始终可以将其包装在一个函数中:

def multiassign(d, keys, values):
    d.update(zip(keys, values))
Run Code Online (Sandbox Code Playgroud)

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

def multiassign(d, keys, values):
    for k, v in zip(keys, values):
        d[k] = v
Run Code Online (Sandbox Code Playgroud)

或者甚至可以编写一个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)
Run Code Online (Sandbox Code Playgroud)

现在:

>>> 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}
Run Code Online (Sandbox Code Playgroud)

请注意,显然不再可能使用元组作为键EasyDict

另外,如果您打算将此用于严重的事情,则可能需要改进错误处理。(d['a', 'b'] = 1将给出有关的神秘消息zip argument #2 must support iterationd['a', 'b', 'c'] = 1, 2将默默地工作,而对此无效c,等等)


Skl*_*vit 5

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

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)
Run Code Online (Sandbox Code Playgroud)

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