On Sun, Aug 21, 2016 at 6:53 AM, Michael Selik <michael.se...@gmail.com> wrote:
> For that to make sense, Iterable should be a parent of C, or C should be a
> subclass of something registered as an Iterable. Otherwise it'd be creating
> a general recommendation to say ``__iter__ = None`` on every non-Iterable
> class, which would be silly.

Iterable is a one-trick pony ABC that formerly just checked for an
__iter__ method using any("__iter__" in B.__dict__ for B in
C.__mro__). It was mentioned that the default __getitem__ iterator can
be avoided by defining __iter__ as a callable that either directly or
indirectly raises a TypeError, but that's an instance of Iterable,
which is misleading.

In 3.6 you can instead set `__iter__ = None`. At the low-level,
slot_tp_iter has been updated to look for this with the following
code:

    func = lookup_method(self, &PyId___iter__);
    if (func == Py_None) {
        Py_DECREF(func);
        PyErr_Format(PyExc_TypeError,
                     "'%.200s' object is not iterable",
                     Py_TYPE(self)->tp_name);
        return NULL;
    }

At the high level, Iterable.__subclasshook__ calls _check_methods(C,
"__iter__"):

    def _check_methods(C, *methods):
        mro = C.__mro__
        for method in methods:
            for B in mro:
                if method in B.__dict__:
                    if B.__dict__[method] is None:
                        return NotImplemented
                    break
            else:
                return NotImplemented
        return True
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to