Хочу поделиться некоторыми неожиданно полезными функциями, которыми обладают типы данных Python list
, set
и tuple
. Недавние экспериметы стали для меня своего рода открытием, которое хотелось бы донести до вас, коллеги-программисты.
Наборы (sets)
Самая интересная часть. Проверим, что делают с заданными операндами операторы <
, <=
, >
, >=
. Отчасти очевидно, что оператор ==
делает с наборами, но есть интересная особенность поведение при упорядочинии наборов. Если вы не задумывались об этом раньше, прежде чем читать дальше, попробуйте угадать, как работают операторы сравнения.
{'bread'} <= {'bread', 'butter'} # True {'bread', 'jam'} <= {'bread', 'butter'} # False {'bread'} <= {'bread'} # True
Верно! <=
перегружен набором issubset
. Оператор <
определено работает совсем иначе:
{'bread'} < {'bread', 'butter'} # True {'bread'} < {'bread'} # False
Разница в том, что <
определяет, является ли левый операнд строгим подмножеством правого операнда. Это означает, что левый операнд является подмножеством правого операнда, но не равен ему. Это может быть полезным различием, особенно если учесть, что в наборе нет методов isstrictsubset
или isstrictsuperset
. Не буду вдаваться в подробности поведения >
и >=
, потому как думается, что вы сами можете более или менее заменить подмножество надмножеством и выполнить алгебраический эквивалент умножения на -1
в приведенном выше разделе. Сделаем это:
{'bread', 'butter'} >= {'bread'} # True {'bread', 'jam'} >= {'bread', 'butter'} # False {'bread'} >= {'bread'} # True {'bread', 'butter'} > {'bread'} # True {'bread'} > {'bread'} # False
Теперь вы можете связать сравнения с наборами:
{'bread'} <= {'bread', 'butter'} <= {'bread', 'butter', 'eggs'} # True
Здесь приведён эквивалентный код с использованием issubset
, который подверждает то, как же далеко мы продвинулись:
{'bread'}.issubset({'bread', 'butter'}) and {'bread', 'butter'}.issubset({'bread', 'butter', 'eggs'})
Бонус
Скромный оператор ^
есть перегруженная симметричная разница. Что это значит? Это набор элементов, которые есть в одном из, но не одновременно, левом и правом операнде:
def symmetric_difference(a: set, b: set) -> set: return {elt for elt in a | b if (elt in a) ^ (elt in b)} symmetric_difference({'bread', 'butter'}, {'bread', 'jam'}) # {'butter', 'jam'} {'bread', 'butter'} ^ {'bread', 'jam'} # {'butter', 'jam'}
Обратите внимание на ^
в понимании набора. Это в чистом виде XOR
!
Списки (list), кортежи (tuples), строки (strings). О, мой бог!
Операторы сравнения в списках, кортежах и строках работают одинаково. Операторы <
, <=
, >
, >=
определяют лексикографический порядокએ, который является способом упорядочивания последовательностей объектов на основе порядка их элементов. Это концепция алфавитного порядка, обобщены на последовательности, содержащие любой тип объекта с определенными операторами <
и >
. Здесь вообще всё становится странно!
Начнем со строк:
'01' == '01' # True '01' < '10' # True '11' < '2' # True '2' > '10' > '1' # True
Обратите внимание, что со списками это работает точно так же:
[0, 1] == [0, 1] # True [0, 1] < [1, 0] # True [1, 1] < [2] # True [2] > [1, 0] > [1] # True
И с кортежами:
(0, 1) == (0, 1) # True (0, 1) < (1, 0) # True (1, 1) < (2,) # True (2,) > (1, 0) > (1,) # True
Бонус
Можно даже сравнить списки разнородных типов:
[2, 'a'] < [2, 'b'] # True [2, [1, 0]] < [2, [2, 1]] # (: # True
Просто убедитесь, что типы совпадают поэлементно:
[3, 4] < [3, 'a'] # TypeError: '<' not supported between instances of 'int' and 'str'
Заключение
Я надеюсь, что это маленькое исследование заставило вас задуматься о том, что ваш язык программирования может и должен делать, а не о повторном использовании фрагментов кода, которые вы уже где-то видели. В следующий раз, когда вы думаете о чем-то и задаетесь вопросом, работает ли это — попробуйте!
Если вам известно о необычном поведении операторов в Python или любом другом языке рограммирования, поделитесь пожалуйста в комментариях!
Использованы материалы
Три загадочные особенности Python, опубликовано К ВВ, лицензия — Creative Commons Attribution-NonCommercial 4.0 International.
Респект и уважуха