aa ac ae ca cc ce ea ec ee by contrastour earlier squares example supports just one active iterationunless we call squares again in nested loops to obtain new objects herethere is just one skipob ject iterablewith multiple iterator objects created from it classes versus slices as beforewe could achieve similar results with built-in tools--for exampleslicing with third bound to skip itemss 'abcdeffor in [:: ]for in [:: ]print( yend='new objects on each iteration aa ac ae ca cc ce ea ec ee this isn' quite the samethoughfor two reasons firsteach slice expression here will physically store the result list all at once in memoryiterableson the other handproduce just one value at timewhich can save substantial space for large result lists secondslices produce new objectsso we're not really iterating over the same object in multiple places here to be closer to the classwe would need to make single object to step across by slicing ahead of times 'abcdefs [:: 'acefor in sfor in sprint( yend='same objectnew iterators aa ac ae ca cc ce ea ec ee this is more similar to our class-based solutionbut it still stores the slice result in memory all at once (there is no generator form of built-in slicing today)and it' only equivalent for this particular case of skipping every other item because user-defined iterables coded with classes can do anything class can dothey are much more general than this example may imply though such generality is not required in all applicationsuser-defined iterables are powerful tool--they allow us to make arbitrary objects look and feel like the other sequences and iterables we have met in this book we could use this technique with database objectfor exampleto support iterations over large database fetcheswith multiple cursors into the same query result iterable objects__iter__ and __next__