#18963 closed Cleanup/optimization (fixed)
Pattern for object model compatibility isn't friendly for subclasses
| Reported by: | Aymeric Augustin | Owned by: | Aymeric Augustin |
|---|---|---|---|
| Component: | Python 3 | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
In the Python 3 documentation I recommended the following pattern for iterators:
class MyIterator(object):
def __iter__(self):
return self # implement some logic here
def __next__(self):
raise StopIteration # implement some logic here
next = __next__ # Python 2 compatibility
A downside is that if a subclass overrides __next__, it also has to repeat next = __next__. This is tricky.
As of [20012b96] Django bundles six 1.2, which introduced six.Iterator to solve this problem.
This problem cannot cause regressions for people who have working code on Python 2, because they override next, not __next__. However I'd like to take advantage of six.Iterator since it's technically more correct.
The same problem exists with __nonzero__ = __bool__, __div__ = __truediv__ and __idiv__ = __truediv__.
We could use a slightly more verbose pattern:
class Foo(object):
def __nonzero__(self):
return self.__bool__()
six.Iterator uses type(self).__next__(self) rather than self.__next__(). I assume there's a good reason but I haven't figured it out. I'd like to understand it before making a decision.
Change History (3)
comment:1 by , 13 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
| Triage Stage: | Unreviewed → Accepted |
comment:2 by , 13 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
Answer from #python-dev on the last question:
It's safer to mimick the interpreter's behavior closely, so let's adopt the same pattern.