New submission from Andrew Barnert: Serhiy Storchaka raised an issue (http://bugs.python.org/msg256910) with static type hints on #25864 (http://bugs.python.org/issue25864), which I believe also applies to runtime ABCs.
Consider this class, which uses `[]` in a way similar to generic types: class Thing: def __getitem__(self, specialization): return type(self)._specialize(specialization)(self) def __len__(self): return len(self._specializations) Because this type looks like it supports the old-style sequence protocol, calling either `iter` or `reversed` on an instance will successfully return a useless iterator. (You may get an error when you start trying to iterate it, but you may not even then.) You don't want that, so you add either this: __iter__ = None __reversed__ = None ... or this: def __iter__(self): raise TypeError('not iterable') def __reversed__(self): raise TypeError('not iterable') Unfortunately, doing either means that `issubclass(Thing, collections.abc.Iterable)` now returns true. Which is the exact opposite of the intention of that check. (The same is true for `typing.Iterable` and `typing.Reversible`.) So, fixing the problem for duck typing creates the equivalent problem for explicit typing. There are a few possible solutions here: 1. Maybe document it, otherwise do nothing. 2. Change the ABCs to check that the dunder method exists and is not None (or is callable, or is a non-data descriptor). Then, the one way to opt out is to assign `__iter__ = __reversed__ = None`. 3. Add an `ABC.unregister` method that can be used to explicitly state that this type does not support that ABC, regardless of what its `__subclasshook__` says. Possible argument for #1: `Iterable` rarely has a problem. (Types that use `__getitem__` for something completely un-sequence-like, like `typing`'s generic types, usually don't have `__len__`. Types that have both `__getitem__` and `__len__`, like mappings, usually have a reasonable alternative `__iter__` to offer.) `Reversible` would have a problem if there was such an ABC, but there isn't. Off the top of my head, I can't think of any of the other implicit ABCs that are susceptible to this problem. The counter-argument is that static typehinting definitely does have this problem (https://github.com/ambv/typehinting/issues/170), and, depending on how that's solved, it may well make sense to use the same solution here. If we do need a solution, #2 seems better than #3 (or anything else I could think up). The only problem there is that `def __iter__(self): raise TypeError('not iterable')` gives you a nicer error than `__iter__ = None`. ---------- components: Library (Lib) messages: 257052 nosy: abarnert priority: normal severity: normal status: open title: Implicit ABCs have no means of "anti-registration" versions: Python 3.6 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue25958> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com