Чому набори Python не розуміють '+'?


90

Я хотів би знати, чому це дійсно:

set(range(10)) - set(range(5))

але це недійсно:

set(range(10)) + set(range(5))

Це тому, що "+" може означати як перетин, так і об'єднання?


3
|означає союз. Що ти питаєш?
S.Lott

13
Це тому, що Гвідо вибрав різні оператори для перетину та об’єднання.
Девід Хеффернан,

3
@ Девід Хеффернан, Гвідо зазвичай не робить справи без причини або хоча б якогось керівного принципу - саме це робить Python таким чудовим.
Марк Ренсом

1
@Mark О, я впевнений, що він зробив це з поважної причини.
Девід Хеффернан,

1
Якби тільки ~двійковий оператор, то ви могли б мати як |для + об'єднання, так і ~для різниці, яка є набагато більш збалансованою.
Matt Joiner

Відповіді:


109

Набори Python не мають реалізації для +оператора.

Можна використовувати | для об'єднання множин та &для перетину множин.

Набори реалізують -як встановлену різницю. Ви також можете використовувати ^для симетричної різниці наборів (тобто вона поверне новий набір лише з об'єктами, які відображаються в одному наборі, але не відображаються в обох наборах).


2
Дякую. Я не знав про | та &.
badzil

99

Python вирішив використовувати |замість того, +що об'єднання множин - це поняття, яке тісно пов'язане з булевою диз'юнкцією; Бітові вектори (які в python - це просто int/ long) визначають цю операцію в послідовності булевих значень і називають її "побітовим або". Насправді ця операція настільки схожа на об'єднання множин, що двійкові цілі числа іноді також називають "бітовими наборами", де елементами у множині прийнято вважати натуральні числа.

Оскільки intоператори, подібні до набору, вже визначають як |, &і ^для нового setтипу було природно використовувати той самий інтерфейс.


7
Я думаю, що ця відповідь краще стосується питання "чому" у питанні.
Грег Хендерсхотт

1
Ймовірно. +1 за те, чому. Хоча в одному сенсі, принаймні, хто задає питання, здавалося, задоволений просто знанням того, як зробити об'єднання та перетин.
Platinum Azure

2
@Platinum: Мені подобається відповідати на фактично задане питання, тому, коли приходить хтось інший, хто має це запитання, може побачити всі обґрунтовані відповіді; навіть якщо особа, яка задала оригінальне запитання, рушила далі. Між нами двома ми відповідаємо на це добре.
SingleNegationElimination

1
@TokenMacGuy: "Оскільки Python просто не визначив оператора", також відповідає, чому. :-P
Platinum Azure

15
Я не впевнений, що це так; "Тому що воно блакитне" не пояснює "Чому небо блакитне?"
SingleNegationElimination

36

У теорії множин символ + зазвичай вказує на неперервний союз двох множин. Якщо A і B множини, їх неперервним об'єднанням визначається множина

A + B = {(a, 1) | a in A} U {(b, 2) | b in B}

тобто для побудови неперервного об'єднання ми позначаємо всі елементи A і всі елементи B різними мітками (у прикладі я використовував цифри 1 і 2, але будь-які дві різні "речі" зробили б цю роботу), а потім взяли об'єднання двох отриманих множин. У наведеному вище прикладі я використовував 'U' для об'єднання множин, щоб зробити його більш схожим на звичайні математичні позначення; нижче я використовую позначення Python, тобто '|' для об'єднання та '&' для перетину.

Якщо A і B не перетинаються, A + B має відповідність 1 до 1 з A | B. Якщо вони не є, то всі загальні елементи x в A & B двічі відображаються в A + B: один раз як (x, 1) і один раз як (x, 2).

Отож, оскільки символ '+' має досить усталене значення як операція набору, я вважаю дуже послідовним, що Python не використовує цей символ для об'єднання наборів або перетину. Ймовірно, дизайнери (розробники) Python мали це на увазі, коли обирали оператори набору.


5
Це оптимальна відповідь. Поки не прочитав цю відповідь, я гадав, чому Гвідо перевантажив |оператора для наборів об'єднань, але не зміг зрозуміти, чому Гвідо також уникнув перевантаження +оператора для об'єднань множин. Зрештою, це призвело б до збереження ортогональності з +перевантаженням оператора для додавання списку. Оскільки відмітною ознакою Пітона є відповідність математичним позначенням (наприклад, jпозначення складної складової комплексних чисел), допитливий вибір Гвідо нарешті має сенс.
Сесіл Каррі

23

Звичайно, вони могли б +робити об’єднання, але тоді все одно знадобився б символ для перетину. |для об'єднання є симетричним &для перетину і, отже, робить кращий вибір.


10

Тому що |означає союз і &означає перетин. Очевидно, немає жодної причини додавати кілька операторів для однієї функції.

Причини використання |та, &ймовірно, сягають побітових операцій. Якщо ви представляєте набір як біти числа, це ті оператори, які ви використовували б для об'єднання та перетину.

+просте не настільки прив’язане до об’єднання і -полягає у встановленні різниці.


3

Оскільки різниця в множинах є дуже корисним і загальновідомим поняттям, але не існує (загальновживаного) поняття „додавання множин“.


1
Союз? Коли ви востаннє чули, як хтось вимовляв „встановити додавання” замість „об’єднання”, або використовував + замість ∪ ?. Іноді +це визначається як додавання членів . Деякі використовують його для симетричної різниці . У будь-якому випадку, будь-який папір, який використовує його, або називає це інакше, або визначає його першим.
Петро Вікторін

1
Хтось може називати це «додаванням набору», якщо не знає правильного терміна. Очевидно, що люди, які знають термін "союз", використовують термін "союз".
пухнастий
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.