Я всегда думал, что нули Python не равны, как это принято во многих других языках и основано на простой логике (если значение неизвестно, как оно может быть равно другому неизвестному?).
Однако недавно я попробовал это и обнаружил, что:
Python 3.10.2
>>> None == None
True
Всегда ли так было? Если нет, то в какой версии это изменилось?
Я несколько удивлен, что в официальной документации None
по-прежнему упоминается как «Нулевой объект».
SQL NULL подобен NaN. Python Нет.
Очевидно, это так, основываясь на ответе на мой вопрос, который фактически спрашивает, похож ли Python None на SQL NULL...
Никто не всегда был равен самому себе в питоне. «Нет == Нет» всегда оценивается как истина.
Как видно из этой документации https://docs.python.org/3/c-api/none.html
Поскольку None является синглтоном, достаточно проверить идентичность объекта (используя == в C).
Не то чтобы я вам не верил, но есть ли у вас ссылка на то, где это определено в спецификации языка?
Конечно, если не указано иное, вы ожидаете, что все значения будут равны сами себе.
@CalebCarson: на самом деле это ничего не говорит о том, как None ведет себя при сравнении Python ==. Он делает краткую ссылку на совершенно другой оператор C ==, но ничего не говорит о Python ==.
@ user2357112, конечно, вы могли бы явно задокументировать противоположное поведение в Python, не противоречащее документам C API, но в отсутствие этой явной документации (поскольку существует для NaN f/e), поведение по умолчанию для синглтона очень актуально.
@kindall Вот почему я прошу документацию 🙄
@user2357112 user2357112 Там прямо сказано, что «достаточно проверки идентичности объекта».
Поскольку None является синглтоном (доступ к которому осуществляется только из одной точки памяти), он может быть только одним значением, поэтому == самому себе всегда будет иметь значение True. Надеюсь, это проясняет ситуацию @ user2357112
Каждый объект сравнивается с самим собой, если иное не определено и не задокументировано; None
не задокументирован иначе, а type(None).__eq__
не определен и наследуется от object
.
@CalebCarson: у вас могут быть синглтоны, которые не сравниваются сами с собой. Синглтонность здесь не особенная. Поведение ==
по умолчанию для одиночек — это поведение по умолчанию для объектов в целом, и его можно переопределить, как и для любого другого объекта.
@Dommondke: В контексте это означает, что вам не нужна проверка типа, чтобы проверить, является ли значение None, как вы бы проверили, было ли значение int или что-то в этом роде, потому что есть только один экземпляр типа None, поэтому сравнения идентичности с None достаточно для проверки типа. На самом деле это ничего не говорит о том, как ведут себя сравнения Python ==
с None.
Как указывалось выше, это связано с тем, как None == None оценивается __eq__.
None является одноэлементным объектом, что означает, что в любой момент времени в памяти находится только один его экземпляр. Когда вы присваиваете переменной None, вы просто создаете ссылку на этот единственный экземпляр None.
Итак, ваш пример похож на высказывание «указывает ли None на тот же объект в памяти, что и None?». Ответ положительный, поэтому __eq__ выполнено (Истина).
Эта ссылка очень подробно объяснит равенство, если вы хотите прочитать об этом.
None == None
теоретически может быть определен (и реализован) как False
, даже если None
является тем же объектом в памяти, что и None
.
@ mkrieger1 mkrieger1 вы предлагаете реализовать проверку на равенство способом, отличным от реализации stdlib? В этом случае я согласен, но я не думаю, что это будет в рамках этого вопроса. Python всегда избегал двусмысленности, и оценка None == None (или None is None) всегда будет и должна возвращать True.
float.__eq__
нервно оглядывается.
@chepner Да ... ну ... я не могу удовлетворить их всех, ха-ха. Мне неловко говорить, что есть необходимые исключения, которые мы должны учитывать, но, к сожалению, здесь это так. Я действительно думаю, что понимание проблемы с представлением чисел с плавающей запятой в двоичном виде является одним из тех, хотя рано или поздно каждый наткнется на эту проблему в своей работе, я думаю.
float
(или, точнее, арифметика с плавающей запятой IEEE 754) имела больше практических интересов, чем математическая чистота :)
Нет явного утверждения, что None == None
истинно, но еще в Python 1.5.2 есть два утверждения, которые подразумевают это.
Во-первых, в обсуждении оператора равенства:
Сравнение объектов одного типа зависит от типа:
- Числа сравниваются арифметически.
- Строки сравниваются лексикографически с использованием числовых эквивалентов (результат встроенной функции
ord()
) их персонажи.- Кортежи и списки сравниваются лексикографически с использованием сравнения соответствующих элементов.
- Сопоставления (словари) сравниваются посредством лексикографического сравнения их отсортированных (ключ, значение) списков.
- Большинство других типов сравниваются неравными, если только они не являются одним и тем же объектом; выбор, считать ли один объект меньшим или большим чем другой производится произвольно, но последовательно в рамках одного выполнение программы.
Однако при каждом использовании None
относится к одному и тому же объекту
2.1.7.7 Нулевой объект
Этот объект возвращается функциями, которые явно не возвращают ценить. Он не поддерживает никаких специальных операций. Существует ровно один ноль объект с именем
None
(встроенное имя).Пишется как
None
.
Я не путаю это с
NaN
, @Barmar, вопрос оNone
, а не оNaN
. На самом деле я думал о таких вещах, как SQLNULL
.