Цель перегрузки оператора идентификации

Почему в Python невозможно перегрузить оператор сравнения идентичности? Любой другой оператор сравнения можно настроить, так почему бы не сравнить идентичность?


person RyPeck    schedule 18.01.2014    source источник
comment
Потому что это должна быть личность? Только перегрузка == имеет смысл. В конце концов, должен быть хотя бы один оператор, которому вы можете доверять. знак равно   -  person Ry-♦    schedule 18.01.2014
comment
Для практических целей вам нужен гарантированный способ сравнения идентичности объектов, а is принадлежит Python. Важно иметь непереопределяемые операторы для определенных вещей (например, логических операций). Однако вы можете настроить поведение ==. У вас есть конкретный вариант использования, когда вы чувствуете необходимость переопределить is, но не можете предоставить __eq__ метод для настройки ==?   -  person Joshua Taylor    schedule 19.01.2014
comment
У меня нет конкретного варианта использования, просто возник вопрос.   -  person RyPeck    schedule 19.01.2014


Ответы (3)


Языки программирования, поддерживающие объекты с изменяемым состоянием, обычно предоставляют оператор, который может проверить, действительно ли два объекта являются одним и тем же объектом. «Одинаковые» в данном случае означает, что объекты на самом деле являются одним и тем же объектом (например, одним и тем же блоком байтов в памяти (или тем же способом, выбранным разработчиками компилятора для представления объектов). Однако для многих типов структур данных существуют другие типы отношений эквивалентности, которые могут быть более заметными для программиста. Например, при наличии интерфейса List программист может заботиться только о том, содержат ли два списка эквивалентные элементы в одном и том же порядке. Это действительно имеет значение только в том случае, если есть некоторые способ различения двух списков с эквивалентными элементами.Поскольку многие языки программирования поддерживают изменяемое состояние, операции, которые изменяют состояние объекта, являются именно таким способом, которым такие объекты могут быть различимы.

Например, учитывая изменяемую реализацию списков, мы могли бы иметь:

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. ##

В функциональном языке программирования, который не имеет изменяемого состояния, или даже на языке, который имеет изменяемое состояние, но в котором мы используем функциональные стили, мы не будем деструктивно изменять такой список, а скорее будем добавить операция вернет новый список (возможно, разделяя структуру с другими). В таком случае можно было бы иметь только один список для любой последовательности элементов, поэтому мы могли бы иметь:

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).

Стоит отметить, что во многих языках реализация оператора равенства по умолчанию является идентификатором объекта. Это может быть приятно, потому что идентичность объекта обычно проверяется гораздо быстрее, чем другие, более сложные отношения равенства.

person Joshua Taylor    schedule 20.01.2014

Вы не можете переопределить 'is', потому что он проверяет, являются ли два объекта одним и тем же объектом, сравнивая их адреса в памяти (т. Е. Сравнение указателей).

person Shv    schedule 18.01.2014
comment
@RyPeck, я согласен с shv, потому что это сравнение указателей, которое вы не можете переопределить. - person secumind; 18.01.2014
comment
@Shv Я не думаю, что это объясняет, почему вы не можете его отменить. Я полностью согласен с тем, что должен быть оператор идентификации, который нельзя переопределить, но только потому, что is является сравнением идентичности, не означает, что он не может быть переопределен. Например, метод equals по умолчанию в Java выполняет сравнение идентичности, но его можно переопределить. Конечно, Java по-прежнему предоставляет ==, который нельзя переопределять, и обеспечивает сравнение идентичностей. Я думаю, что, возможно, здесь отсутствует предпосылка о том, что непревзойденное сравнение идентичности очень желательно, а is принадлежит Python. - person Joshua Taylor; 19.01.2014

Проще говоря, потому что цель оператора идентификации - проверить идентичность. Идентичность означает «то, чем на самом деле является объект». Весь смысл оператора состоит в том, чтобы иметь возможность проверить, «действительно ли два объекта» являются одним и тем же объектом, а не то, «хотят ли они» считаться одним и тем же в соответствии с их собственными правилами.

person BrenBarn    schedule 18.01.2014