Что означает `**` в выражении `dict (d1, ** d2)`?

Меня заинтриговало следующее выражение Python:

d3 = dict(d1, **d2)

Задача состоит в том, чтобы объединить 2 словаря в третий, и приведенное выше выражение отлично справляется с задачей. Меня интересует оператор ** и что именно он делает с выражением. Я думал, что ** был оператором мощности, и еще не видел, чтобы он использовался в контексте выше.

Полный фрагмент кода таков:

>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'c': 3, 'd': 4}
>>> d3 = dict(d1, **d2)
>>> print d3
{'a': 1, 'c': 3, 'b': 2, 'd': 4}

person λ Jonas Gorauskas    schedule 12.02.2010    source источник
comment
Следует отметить, что GvR считает это выражение презренным   -  person elhefe    schedule 24.08.2012
comment
Это работает, только если ключи в d2 являются строками, по крайней мере, в Python 3.   -  person Brent Bradburn    schedule 18.08.2013
comment
О, круто, я не понимал, что это вообще будет работать в Python 2. Я полагаю, что преимущество dict(d1, **d2) перед dict(**d1, **d2), {d1, **d2} или {**d1, **d2} - это работает в Python 2. Я думаю, что последний синтаксис является предпочтительным синтаксисом в Python 3 , потому что он краткий и последовательный. Но приятно знать, что в Python 2 есть способ сделать это, по крайней мере, с помощью строковых ключей, даже если это выглядит немного хакерским.   -  person Michael Scheper    schedule 13.06.2017


Ответы (6)


** в списках аргументов имеет особое значение, как описано в разделе 4.7 учебник. Словарь (или подобный словарю) объект, переданный с **kwargs, расширяется в аргументы ключевого слова для вызываемого объекта, подобно тому, как *args раскрывается в отдельные позиционные аргументы.

person Thomas Wouters    schedule 13.02.2010
comment
У меня вопрос, зачем использовать dict(d1, **d2), а не dict(**d1, **d2). Последний вариант мне кажется более чистым, и конечный результат кажется таким же. Я что-то упускаю? - person Michael Scheper; 13.06.2017
comment
Не бери в голову; Я не понимал, что мы говорим о Python 2, где dict(d1, **d2) кажется единственным способом. Приятно осознавать, что это даже возможно. Я думаю, что {**d1, **d2} является предпочтительным синтаксисом в Python 3, поскольку он согласован и краток. - person Michael Scheper; 13.06.2017

** превращает словарь в параметры ключевого слова:

>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'c': 3, 'd': 4}
>>> d3 = dict(d1, **d2)

Становится:

>>> d3 = dict(d1, c=3, d=4)
person Mark Byers    schedule 13.02.2010
comment
вместо этого он становится dict(d1, c=3, d=4). - person Thomas Wouters; 13.02.2010
comment
Да, спасибо! Я знал, что хотел напечатать, но мои пальцы не понимали сообщения ... - person Mark Byers; 13.02.2010

В Python любая функция может принимать несколько аргументов с *;
или несколько аргументы ключевого слова с **.

Пример на принимающей стороне:

>>> def fn(**kwargs):
...   for kwarg in kwargs:
...     print kwarg
... 
>>> fn(a=1,b=2,c=3)
a
c
b

Пример вызывающей стороны (спасибо Томасу):

>>> mydict = dict(a=1,b=2,c=3)
>>> fn(**mydict)
a
c
b
person mechanical_meat    schedule 12.02.2010
comment
Обратите внимание, что это демонстрирует принимающую, а не вызывающую сторону. - person Thomas Wouters; 13.02.2010
comment
Еще раз спасибо Томас :-D Добавлен пример вызывающей стороны. - person mechanical_meat; 13.02.2010

Также стоит упомянуть о механике конструктора dict. Он принимает исходный словарь в качестве своего первого аргумента, а также может принимать аргументы ключевого слова, каждый из которых представляет новый член для добавления во вновь созданный словарь.

person mantrapeze    schedule 13.02.2010

у вас есть ответ оператора **. вот еще один способ добавить словари

>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'c': 3, 'd': 4}
>>> d3=d1.copy()
>>> d3.update(d2)
>>> d3
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
person ghostdog74    schedule 13.02.2010

Этот оператор используется для распаковки списка аргументов: http://docs.python.org/tutorial/controlflow.html#unpacking-argument-lists.

person Sridhar Iyer    schedule 13.02.2010