2014-01-19 2 views
11

Можно ли присвоить значения более чем одним клавишам словаря более кратким способом, чем приведенный ниже?Несколько назначений в словарь python

Я имею в виду, пусть d быть словаря инициализируется, как показано ниже:

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

Для присвоения значений нескольким клавишам, что нужно сделать это:

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

Могу ли я достичь же с чем-то вроде этого :

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

Спасибо.

ответ

25

Вы можете использовать dict.update:

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

Это перепишет значения для существующих ключей и добавить новые значения ключа-пару ключей, которые еще не существуют.

+0

Yup, это уверенный работ. Я знал 'update()', но ... Спасибо. – ozi

+4

Вы также можете записать это как 'd.update (a = 10, b = 200, c = 300)', если ключи являются действительными идентификаторами (как вы можете в конструкторе). – abarnert

+0

@abarnert да хорошее предложение :) –

0

Вы можете использовать понимание словаря, например.

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

выход:

{ 'а': 1, 'с': 3, 'B': 2}

+3

С данными в этом формате 'dict (zip (буквы, nos))' будет аккуратно – jonrsharpe

4

Вы можете всегда обернуть его в функции:

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 и т.д.)

1

Сравнение скорости, от худшего к лучшее:

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) 

Таким образом, явный победитель - это воссоздание словаря из словарей.

Смежные вопросы