User-defined classes interact with the Python virtual machine via special methods (also called "magic methods"). For example, for a class to support addition it must implement the __add__ and __radd__ special methods. When the expression a + b is evaluated, the Python virtual machine will call type(a).__add__(a, b), and if that is not implemented it will call type(b).__radd__(b, a).

Since the virtual machine calls these special methods for common expressions, users of the class will expect these operations to raise standard exceptions. For example, users would expect that the expression a.b may raise an AttributeError if the object a does not have an attribute b. If a KeyError were raised instead, then this would be unexpected and may break code that expected an AttributeError, but not a KeyError.

Therefore, if a method is unable to perform the expected operation then its response should conform to the standard protocol, described below.

If the method always raises as exception, then if it is intended to be an abstract method, the @abstractmethod decorator should be used. Otherwise, ensure that the method raises an exception of the correct type, or remove the method if the operation does not need to be supported.

In the following example, the __add__ method of A raises a TypeError if other is of the wrong type. However, it should return NotImplemented instead of rising an exception, to allow other classes to support adding to A. This is demonstrated in the class B.

In the following example, the __getitem__ method of C raises a ValueError, rather than a KeyError or IndexError as expected.

In the following example, the class __hash__ method of D raises NotImplementedError. This causes D to be incorrectly identified as hashable by isinstance(obj, collections.abc.Hashable); so the correct way to make a class unhashable is to set __hash__ = None.

  • Python Language Reference: Special Method Names.
  • Python Library Reference: Exceptions.