__builtin__.iterator Does Not Exist?
Solution 1:
Not all internal object types are listed in the __builtin__
structure, no.
You won't find the method type there either, nor the generator type, or many others. Only names that you'd actually use in your Python code are listed in that namespace.
Some such types are listed in the types
module, but the iterator type isn't, because, as the source states:
# Iterators in Python aren't a matter of type but of protocol. A large# and changing number of builtin types implement *some* flavor of# iterator. Don't check the type! Use hasattr to check for both# "__iter__" and "next" attributes instead.
If you wanted to test if something is an iterator, use the Iterator
ABC instead:
import collections
ifisinstance(something, collections.Iterator):
If you have some obscure need to get the iterator
type as returned for strings, you can use type()
on it:
>>> type(iter('123'))
<type'iterator'>
and store that; that's how the types
module produces many of its references.
However, know that that type is not universal:
>>>iterator = type(iter(''))>>>isinstance(iter([]), iterator)
False
>>>iter([])
<listiterator object at 0x108e72d50>
>>>isinstance(reversed([]), iterator)
False
>>>reversed([])
<listreverseiterator object at 0x108e72d50>
yet testing with the ABC does recognise them all:
>>>from collections import Iterator>>>isinstance(iter([]), Iterator)
True
>>>isinstance(iter(reversed([])), Iterator)
True
>>>isinstance(iter(''), Iterator)
True
If you need to create an iterator, then either produce a sequence and return the result of iter()
on that, or produce an iterator type yourself. The latter is easy enough, either use a generator expression, use a generator function for __iter__
or give your type a __next__
method that produces an item each time it is called (and have __iter__
return self
).
Solution 2:
Worse than that, it is a type that is not immediately a class.
>>> type(iter(range(5)))
<type'listiterator'>
When you ask a (new-style) class instance for its type it says it is a class.
>>>classX(object): pass...>>>type(X())
<class '__main__.X'>
(And why would they implement new functionality with an old-style class?)
Given that, if you got a hold of it what would you do with it?
OK, so you can get it, and if you poke around, there is a class in there somewhere
>>>it = iter(range(5)).__class__
But you can't inherit from it
>>> classit2(it): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclassbasestype'listiterator'isnot an acceptable base type
And monkey-patching it seems outright dastardly. I hope something would stop you.
You also can't instantiate it directly:
>>> x = it()
Traceback (most recent calllast):
File "<stdin>", line 1, in<module>
TypeError: cannot create'listiterator' instances
So isn't it better for it to just pretend not to exist, rather than showing up and apologizing for all the normal things it cannot do?
The same goes for things like function, int, double, str, etc. Most of those at least let you instantiate them, but they are not really classes, and so going much farther is spooky.
Post a Comment for "__builtin__.iterator Does Not Exist?"