Три загадочные особенности Python

Хочу поделиться некоторыми неожиданно полезными функциями, которыми обладают типы данных 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 или любом другом языке рограммирования, поделитесь пожалуйста в комментариях!

Использованы материалы 3 Lesser Known Python Features

Print Friendly, PDF & Email

CC BY-NC 4.0 Три загадочные особенности Python, опубликовано К ВВ, лицензия — Creative Commons Attribution-NonCommercial 4.0 International.


Респект и уважуха

Добавить комментарий