Почему в Python это невозможно сделать оператору overload the identity comparison? Любой другой оператор сравнения можно настроить, так почему бы не сравнить идентичность?Назначение перегрузки идентификатора оператора
ответ
Языки программирования, которые поддерживают объекты с изменчивым состоянием, обычно предоставляют оператору, который может проверить, являются ли фактически двумя объектами тот же объект. «То же самое» в этом случае означает, что объекты на самом деле являются одним и тем же объектом (например, один и тот же кусок байтов в памяти (или, однако, разработчики компилятора предпочитают представлять объекты). Однако для многих типов структур данных существуют другие типы отношений эквивалентности, которые могут быть более заметными для программиста. Например, с учетом интерфейса List программисту может быть только забота о том, содержат ли два списка эквивалентные элементы в одном порядке. Это действительно имеет значение только в том случае, если есть некоторые так как многие языки программирования поддерживают изменяемое состояние, операции, которые мутируют состояние объекта, - это именно такой способ, в котором такие объекты можно отличить.
Например, учитывая изменчивую реализацию списков, мы могли бы h пр:
x = make a list of 1 2 3
y = x
z = make a list of 1 2 3 4
x same as y? yes.
x equal to y? yes.
x same as z? no.
x equal to z? no.
add 4 to end of x
x same as y? yes.
x equal to y? yes.
x same as z? no.
x equal to z? yes. ##
В функциональном языке программирования, который не имеет изменяемое состояния, или даже на языке, который действительно имеет изменяемое состояние, но в которых мы используем функциональные стили, мы не деструктивно изменить список вроде этого, а скорее add операция вернет новый список (возможно, совместное использование структуры с другими). В таком случае, можно было бы иметь только один список для любой последовательности элементов, таким образом, мы могли бы:
x = make a list of 1 2 3
y = x
z = make a list of 1 2 3 4
x same as y? yes.
x equal to y? yes.
x same as z? no.
x equal to z? no.
x' = add 4 to end of x
x same as y? yes.
x equal to y? yes.
x same as z? no.
x equal to z? no.
x same as x'? no.
x equal to x'? no.
x' same as x? no.
x' equal to x? no.
x' same as z? yes. ## or no, depending on implementation
x' equal to z? yes.
x' same as x'? yes.
x' equal to x'? yes.
Тот факт, что
x same as y? yes.
x equal to y? yes.
x same as z? no.
x equal to z? no.
остается неизменным в течение может быть полезным в рассуждения о поведении программ.
Когда мы программируем объектно-ориентированным способом, идентичность объекта является важной концепцией и на самом деле является одним из примитивов языка, как и логические операторы, или числовое сравнение. Если это можно переопределить, целый класс оптимизаций не может быть выполнен, и вы можете ввести довольно сложную задачу для отслеживания ошибок. Например, рассмотрим (возможно надуманный пример):
# frob x and y, but never frob an object twice
frobBoth x y
if x same as y # **
frob x
else
frob x
frob y
end if
Если вы можете переопределить same as
, то вы не могли бы frob
как x
и y
, потому что same as
может вернуться верно, даже если x
и y
не тот же объект ,
В языках, где идентификация объекта может быть важна, должен быть оператор идентичности объекта, который нельзя переопределить.Также обычно полезно ввести оператор равенства, который может быть переопределен каким-то образом, так что легко проверить, эквивалентен ли один из них каким-либо полезным способом (и это будет специфично для типа объекта).
- В Python, тождественный оператор является
is
и оператор равенства==
, которые могут быть настроены с помощью метода__eq__
. - В качестве другого примера, в Java идентификатор оператора равен
==
, а оператор равенства -Object.equals(Object)
.
Стоит отметить, что во многих языках, реализация по умолчанию оператора равенства в является идентификатором объекта. Это может быть хорошо, потому что идентификация объекта обычно намного быстрее, чем другие, более сложные отношения равенства.
Проще говоря, поскольку целью оператора идентификации является проверка идентификатор. Идентичность означает «какой объект на самом деле». Вся суть оператора заключается в том, чтобы проверить, являются ли два объекта «действительно» одним и тем же объектом, а не «хотят ли они» считаться одинаковыми в соответствии с их собственными правилами.
Вы не можете переопределить 'is', потому что он проверяет, являются ли два объекта одним и тем же объектом, сравнивая их адреса памяти (то есть сравнение указателей).
@RyPeck, я согласен с shv, потому что это сравнение указателей, вы не можете переопределить его. – secumind
@Shv Я не думаю, что это объясняет, почему вы не можете его переопределить. Я полностью согласен с тем, что должен быть оператор идентичности, который не переопределяем, а просто потому, что 'is' является сопоставлением идентичности, не означает, что он не может быть переопределяемым. Например, метод 'equals' по умолчанию в Java делает сравнение идентичности, но он переопределяем. Конечно, Java по-прежнему предоставляет '==', который является _not_ переопределяемым и обеспечивает сопоставление идентичности. Я думаю, что, возможно, недостающая предпосылка здесь заключается в том, что «неприемлемое сопоставление идентичности очень желательно, а' is' - это Python ». –
Потому что это должно быть личность? Перегрузка '==' является единственной, которая имеет смысл. В конце концов, должен быть хотя бы один оператор, которому вы можете доверять. =) – Ryan
Для практических целей вы хотите иметь гарантированный способ сравнения идентификатора объекта, а 'is' - это Python. Для некоторых вещей важно иметь неперепределяемые операторы (например, логические операции). Вы можете настроить поведение '=='. У вас есть конкретный случай использования, когда вы чувствуете необходимость переопределить 'is', но не можете предоставить метод' __eq__' для настройки '=='? –
У меня нет конкретного варианта использования, только вопрос, который возник. – RyPeck