To address the two examples you brought up:
import itertools
data1 = range(10)
# This creates a NEW list
data1[2:5]
# This creates an iterator that iterates over the EXISTING list
itertools.islice(data1, 2, 5)
data2 = [1, 2, 3]
data3 = [4, 5, 6]
# This creates a NEW list
data2 + data3
# This creates an iterator that iterates over the EXISTING lists
itertools.chain(data2, data3)
There are many reasons why you'd want to use iterators instead of the other methods. If the lists are very large, it could be a problem to create a new list containing a large sub-list, or especially create a list that has a copy of two other lists. Using islice() or chain() allows you to iterate over the list(s) in the way you want, without having to use more memory or computation to create the new lists. Also, as unutbu mentioned, you can't use bracket slicing or addition with iterators.
I hope that's enough of an answer; there are plenty of other answers and other resources explaining why iterators are awesome, so I don't want to repeat all of that information here.
Answer from Cyphase on Stack OverflowTo address the two examples you brought up:
import itertools
data1 = range(10)
# This creates a NEW list
data1[2:5]
# This creates an iterator that iterates over the EXISTING list
itertools.islice(data1, 2, 5)
data2 = [1, 2, 3]
data3 = [4, 5, 6]
# This creates a NEW list
data2 + data3
# This creates an iterator that iterates over the EXISTING lists
itertools.chain(data2, data3)
There are many reasons why you'd want to use iterators instead of the other methods. If the lists are very large, it could be a problem to create a new list containing a large sub-list, or especially create a list that has a copy of two other lists. Using islice() or chain() allows you to iterate over the list(s) in the way you want, without having to use more memory or computation to create the new lists. Also, as unutbu mentioned, you can't use bracket slicing or addition with iterators.
I hope that's enough of an answer; there are plenty of other answers and other resources explaining why iterators are awesome, so I don't want to repeat all of that information here.
itertools.islice can slice iterators.
Indexing only works with sequences.
For example,
In [64]: iterator = (x**2 for x in range(10))
In [65]: list(IT.islice(iterator, 2, 5))
Out[65]: [4, 9, 16]
In [66]: iterator[2:5]
TypeError: 'generator' object has no attribute '__getitem__'
Writing your own generator function could be more readable in such cases. For example:
def items():
start = 0
end = 56
step = 10
while True:
d = {"current": start,
"next": start + step if start + step < end else end if start < end else None,
"default": "value"}
yield d
if start >= end:
break
else:
start += step
if start > end:
start = end
print(list(items()))
output:
[{'current': 0, 'next': 10, 'default': 'value'},
{'current': 10, 'next': 20, 'default': 'value'},
{'current': 20, 'next': 30, 'default': 'value'},
{'current': 30, 'next': 40, 'default': 'value'},
{'current': 40, 'next': 50, 'default': 'value'},
{'current': 50,'next': 56, 'default': 'value'},
{'current': 56, 'next': None, 'default': 'value'}]
From your sequence of tuples, you can do a list comprehension (or a generator expression) like:
[{"current": str(x), "next": str(y), "default": "value"} for x, y in data]
Test Code:
data = ((0, 10), (10, 20), (20, 30), (30, 40), (40, 50), (50, 56), (56, None))
print([{"current": str(x), "next": str(y), "default": "value"} for x, y in data])
Results:
[
{'current': '0', 'next': '10', 'default': 'value'},
{'current': '10', 'next': '20', 'default': 'value'},
{'current': '20', 'next': '30', 'default': 'value'},
{'current': '30', 'next': '40', 'default': 'value'},
{'current': '40', 'next': '50', 'default': 'value'},
{'current': '50', 'next': '56', 'default': 'value'},
{'current': '56', 'next': 'None', 'default': 'value'}
]
On Python 3 you can use the itertools islice to slice the dict.items() iterator
import itertools
d = {1: 2, 3: 4, 5: 6}
dict(itertools.islice(d.items(), 2))
{1: 2, 3: 4}
Note: this solution does not take into account specific keys. It slices by internal ordering of d, which in Python 3.7+ is guaranteed to be insertion-ordered.
To slice a dictionary, Convert it to a list of tuples using d.items(), slice the list and create a dictionary out of it.
Here:
d = {1:2, 3:4, 5:6, 7:8}
To get the first 2 items:
first_two = dict(list(d.items())[:2])
first_two:
{1: 2, 3: 4}