Or replace them with methods that do ANYTHING — always raise an exception, mutate the object, etc.
Python is s dynamic language — ABCs do not change that one bit.
They can be useful, as it is a way to express an intended interface, but they can be abused in an infinite number of ways.
So the fact that calling issubclass() on an object and an ABC does guarantee that the object will work as intended is simply part of the language.
If you want guarantees about types, use a statically typed language.
All this is why I don’t see a use for an ABC that indicates the presence of __getitem__ and nothing else. How is that useful?
By the way, the fact that you can derive from an ABC and override a method with None indicates that an isinstance check with an ABC isn’t really more robust than checking for the attribute anyway.
Using an ABC expresses the *intent* of the class author to provide a certain interface.
Adding a certain magic method also expresses the intent to provide that particular functionality.
Thinking about it a bit more, where ABCs are most useful is when the capture the interface of a built in type: folks can then write type checked code ( either statically or dynamically) that works with externally defined objects: e.g. MutableSequence rather than list.
This is actually more powerful that “classic” duck typing— for example, if you have a MutableSequence, you not only know that you can index it, but that it takes integer indices, and will raise a IndexError if it is an invalid index.
Whereas a MutableMapping will take hashable objects as keys, and you will get a KeyError if it’s invalid.
Plus, of course all sorts of other implied interface and behavior.
So we could have an ABC for each magic method, but what would that actually accomplish?