Message257052
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`. |
|
Date |
User |
Action |
Args |
2015-12-26 22:26:42 | abarnert | set | recipients:
+ abarnert |
2015-12-26 22:26:42 | abarnert | set | messageid: <1451168802.83.0.911068284232.issue25958@psf.upfronthosting.co.za> |
2015-12-26 22:26:42 | abarnert | link | issue25958 messages |
2015-12-26 22:26:42 | abarnert | create | |
|