First of all tgrtim, thank you for taking time out of your day to help me. I do appreciate it. I do have some questions about your response that I hope you can answer for me.
As a rookie, I am going to have to look up some of the things you are talking about. You talk about containers but I find the link to the documentation very technical. Clearly I will need to use youtube and other resources.
“So the closest match to the lessons in my eyes would be to create two classes, one ClassroomOrganizer
that stores and orders the data and a second class, an iterator template than can access the data within a ClassroomOrganizer
instance.”
Sounds good, I keep reading…
"Container types like list
or perhaps a very similar tool like collections.OrderedDict
(a standard module class that acts as a container which can order it’s contents) are iterable . They are not themselves iterators , that task is handled by other types. "
→ okay s I am thinking list and OrderedDict acts as containers that sort things in alphabetical order. I continue reading…
from collections import OrderedDict
foo = iter(list())
bar = iter(OrderedDict())
# Note the types here are not list or OrderedDict but distinct iterators
print(f"{type(foo)!r}") # <class 'list_iterator'>
print(f"{type(bar)!r}") # <class 'odict_iterator'>
As a rookie, when I see that, if I am being honest, I don’t see a difference except that it says that list is a list_iterator and bar dictionary is a dictionary iterator. Other than that I am not quite grasping the point. I continue reading…
This is really an implementation detail but it matters because the behaviour of iterables and iterators is quite different. For a start iterables have no __next__
method (that’s reserved for actual iterators) and calling next()
on an iterable will simply throw exceptions e.g.
→ iterators traverse and use the next method.
→ iterables themselves are not capable of throwing the next method because they are the things be iterated on and have been granted no such capability. in other words a list does not have a built in iterator ability so it cannot work. At least I think that is what you are saying.
" In addition to the behaviour of next()
iterable container types behave differently to iterators when you call iter()
on them. You can get typically get several different independent iterators from a single iterable (maybe a couple of CPython things violate this but it’s rare)"
x = [1, 2, 3,]
y = iter(x)
iter_y = iter(y) # called on an iterator!
print(next(y)) # 1
# It's the SAME ITERATOR!
print(next(iter_y)) # 2
iterator types themselves have different behaviors when you call iter on them.
I believe you are showing y and z are not the same by having them show they are equal to iter(x) and than telling python to compare the two. When it comes back false, this is supposed to be suprising because they were both set equal to the iter(x). I am indeed suprised and do not understand why that is. I continue reading…
print(next(y), next(y)) #2. → I am guessing it traverssed the x = [1, 2, 3,] and came back 2 because next moved to the 2 value.
as for z it is only has next activated once and that makes it only 1. I may be wrong on this.
“In general if you’re defining a new container/collection then making it iterable is wise, making it an iterator probably isn’t (I won’t swear to every possible situation but following this pattern for custom container types is normally a good idea).”
in other words you are saying to making the container iterable is better in general than creating an iterator via iter() and next() is preferable.
I continue reading…
Long story short, for the requirements of this lesson (define a custom iterator) I suggest using at least two classes (an iterable and an iterator).
Okay this is where I am lost. I percieve that you took some time to explain to me that I can make the containers holding the values iterable and that making an iterator is a bad idea.
Has something been made in the code where I can make it a container and make it iterable?