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 <[email protected]>
<http://bugs.python.org/issue25958>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com