Skip to main content
edited body
Source Link
MT0
  • 169.6k
  • 12
  • 67
  • 129

If we have the setup:

class TupleVector(tuple):
    def __eq__(self, other: object) -> bool:
        print("TupleVector.__eq__")
        return super().__eq__(other)
        
class ListVector(list):
    ...

Then:

values = (1,)
print(f"== comparison: {ListVector(values) == TupleVector(values)}")

Outputs:

TupleVector.__eq__
== comparison: False

Showing that the __eq__ call has been reflected to call the right-hand side TupleVector.__eq__().

The reason can be seen if we directly call ListVertorListVector.__eq__():

print(f"__eq__ comparison: {ListVector(values).__eq__(TupleVector(values))}")

Which outputs:

__eq__ comparison: NotImplemented

The Python documentation states:

NotImplemented

A special value which should be returned by the binary special methods (e.g. __eq__(), __lt__(), __add__(), __rsub__(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. __imul__(), __iand__(), etc.) for the same purpose. It should not be evaluated in a boolean context. NotImplemented is the sole instance of the types.NotImplementedType type.

Note: When a binary (or in-place) method returns NotImplemented the interpreter will try the reflected operation on the other type (or some other fallback, depending on the operator). If all attempts return NotImplemented, the interpreter will raise an appropriate exception. Incorrectly returning NotImplemented will result in a misleading error message or the NotImplemented value being returned to Python code. See Implementing the arithmetic operations for examples.

Since listVector.__eq__(other) is not implemented then it goes up the class hierarchy and calls list.__eq__() which returns the NotImplemented object and this causes Python to try to evaluate the reflected operation other.__eq__(listVector), which is implemented and returns a boolean.

If we have the setup:

class TupleVector(tuple):
    def __eq__(self, other: object) -> bool:
        print("TupleVector.__eq__")
        return super().__eq__(other)
        
class ListVector(list):
    ...

Then:

values = (1,)
print(f"== comparison: {ListVector(values) == TupleVector(values)}")

Outputs:

TupleVector.__eq__
== comparison: False

Showing that the __eq__ call has been reflected to call the right-hand side TupleVector.__eq__().

The reason can be seen if we directly call ListVertor.__eq__():

print(f"__eq__ comparison: {ListVector(values).__eq__(TupleVector(values))}")

Which outputs:

__eq__ comparison: NotImplemented

The Python documentation states:

NotImplemented

A special value which should be returned by the binary special methods (e.g. __eq__(), __lt__(), __add__(), __rsub__(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. __imul__(), __iand__(), etc.) for the same purpose. It should not be evaluated in a boolean context. NotImplemented is the sole instance of the types.NotImplementedType type.

Note: When a binary (or in-place) method returns NotImplemented the interpreter will try the reflected operation on the other type (or some other fallback, depending on the operator). If all attempts return NotImplemented, the interpreter will raise an appropriate exception. Incorrectly returning NotImplemented will result in a misleading error message or the NotImplemented value being returned to Python code. See Implementing the arithmetic operations for examples.

Since listVector.__eq__(other) is not implemented then it goes up the class hierarchy and calls list.__eq__() which returns the NotImplemented object and this causes Python to try to evaluate the reflected operation other.__eq__(listVector), which is implemented.

If we have the setup:

class TupleVector(tuple):
    def __eq__(self, other: object) -> bool:
        print("TupleVector.__eq__")
        return super().__eq__(other)
        
class ListVector(list):
    ...

Then:

values = (1,)
print(f"== comparison: {ListVector(values) == TupleVector(values)}")

Outputs:

TupleVector.__eq__
== comparison: False

Showing that the __eq__ call has been reflected to call the right-hand side TupleVector.__eq__().

The reason can be seen if we directly call ListVector.__eq__():

print(f"__eq__ comparison: {ListVector(values).__eq__(TupleVector(values))}")

Which outputs:

__eq__ comparison: NotImplemented

The Python documentation states:

NotImplemented

A special value which should be returned by the binary special methods (e.g. __eq__(), __lt__(), __add__(), __rsub__(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. __imul__(), __iand__(), etc.) for the same purpose. It should not be evaluated in a boolean context. NotImplemented is the sole instance of the types.NotImplementedType type.

Note: When a binary (or in-place) method returns NotImplemented the interpreter will try the reflected operation on the other type (or some other fallback, depending on the operator). If all attempts return NotImplemented, the interpreter will raise an appropriate exception. Incorrectly returning NotImplemented will result in a misleading error message or the NotImplemented value being returned to Python code. See Implementing the arithmetic operations for examples.

Since listVector.__eq__(other) is not implemented then it goes up the class hierarchy and calls list.__eq__() which returns the NotImplemented object and this causes Python to try to evaluate the reflected operation other.__eq__(listVector), which is implemented and returns a boolean.

Source Link
MT0
  • 169.6k
  • 12
  • 67
  • 129

If we have the setup:

class TupleVector(tuple):
    def __eq__(self, other: object) -> bool:
        print("TupleVector.__eq__")
        return super().__eq__(other)
        
class ListVector(list):
    ...

Then:

values = (1,)
print(f"== comparison: {ListVector(values) == TupleVector(values)}")

Outputs:

TupleVector.__eq__
== comparison: False

Showing that the __eq__ call has been reflected to call the right-hand side TupleVector.__eq__().

The reason can be seen if we directly call ListVertor.__eq__():

print(f"__eq__ comparison: {ListVector(values).__eq__(TupleVector(values))}")

Which outputs:

__eq__ comparison: NotImplemented

The Python documentation states:

NotImplemented

A special value which should be returned by the binary special methods (e.g. __eq__(), __lt__(), __add__(), __rsub__(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. __imul__(), __iand__(), etc.) for the same purpose. It should not be evaluated in a boolean context. NotImplemented is the sole instance of the types.NotImplementedType type.

Note: When a binary (or in-place) method returns NotImplemented the interpreter will try the reflected operation on the other type (or some other fallback, depending on the operator). If all attempts return NotImplemented, the interpreter will raise an appropriate exception. Incorrectly returning NotImplemented will result in a misleading error message or the NotImplemented value being returned to Python code. See Implementing the arithmetic operations for examples.

Since listVector.__eq__(other) is not implemented then it goes up the class hierarchy and calls list.__eq__() which returns the NotImplemented object and this causes Python to try to evaluate the reflected operation other.__eq__(listVector), which is implemented.