2016-08-16 1 views
3

Я размышлял над тем, почему стандартный класс dict на языке Python не поддерживает операторы сложения и вычитания, такие как «+» или «+ =», например.Почему словари Python не поддерживают оператор «+»

>>> foo = {'a': 1, 'b': 2} 
>>> bar = {'c': 3, 'd': 4} 

>>> foo + bar 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for +: 'dict' and 'dict' 

мое желаемое за действительное было бы для следующего результата вместо:

>>> foo + bar 
{'a': 1, 'b': 2, 'c': 3, 'd': 4} 

Одинаково почему не __radd__(self, other) результат такой же, как self.__update__(other)?

>>> foo += bar 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for +=: 'dict' and 'dict'  

Кто-нибудь знает исторические причины поведения по умолчанию?

(я признаю, что это может быть неоднозначным, какое значение следует использовать в сценариях, где foo и bar имеют те же основные, но разные значения ключа)

+1

Я думаю, что ваша скотиная концессия - довольно хороший ответ на ваш вопрос. '+' было бы вводящим в заблуждение способом выразить неоднозначное учение. – khelwood

+6

Поскольку выход не был бы тривиальным. Что произойдет, если оба словаря имеют один и тот же ключ? Исключение? значение будет взято из первого словаря? может быть, со второго? Он четко не определен и поэтому не реализован. – DeepSpace

+7

[См. Здесь] (http://bugs.python.org/issue6410) – Sevanteri

ответ

1

Кто-нибудь знает исторические причины поведения по умолчанию?

Гвидо ван Россум отметил, что ему понравилось обновление() лучше и думает + оператор не будет читать ясно в коде.

FWIW, он одобряет PEP 448, который дает свой другой способ сделать это с помощью звездообразной распаковки обобщения:

>>> a = {'a': 1, 'b': 2} 
>>> b = {'c': 3, 'b': 4} 
>>> {**a, **b} 
{'a': 1, 'b': 4, 'c': 3} 

Есть несколько причин, почему + не может быть хорошей идеей. Обычно мы ожидаем, что добавление будет коммутативным, но добавление dict будет терпеть неудачу, если бы были перекрывающиеся ключи с разными значениями. «Обычным» вариантом использования является обновление только dict in-place, но обычная семантика + скопировала содержимое обоих входов для создания нового dict (что несколько расточительно).

Кроме того, у Python есть collections.ChainMap, который заменяет расходы на копирование новым расходом, потенциально имеющим несколько поисков.