File tree Expand file tree Collapse file tree 2 files changed +39
-3
lines changed
Expand file tree Collapse file tree 2 files changed +39
-3
lines changed Original file line number Diff line number Diff line change @@ -132,12 +132,24 @@ def __next__(self):
132132 if kind is _fail :
133133 raise value
134134 return value
135- # Support the `collections.abc.Sequence` API for already-computed items
135+ # Support a subset of the `collections.abc.Sequence` API for already-computed items
136136 def __len__ (self ):
137137 return len (self .memo )
138138 def __getitem__ (self , k ):
139- if k >= len (self .memo ):
140- raise IndexError (f"Attempted to access index { k } of memoized generator; only { len (self .memo )} items available (at least so far)" )
139+ if not isinstance (k , (int , slice )):
140+ raise TypeError (f"Expected an int or slice index, got { type (k )} with value { repr (k )} " )
141+ length = len (self .memo )
142+ if isinstance (k , slice ):
143+ # For slices where at least one item raises an exception, we raise the
144+ # exception that is encountered first when walking the slice.
145+ lst = []
146+ for kind , value in self .memo [k ]:
147+ if kind is _fail :
148+ raise value
149+ lst .append (value )
150+ return lst
151+ if k >= length or k < - length :
152+ raise IndexError (f"memoized generator index out of range; got { k } , with { len (self .memo )} items currently available" )
141153 kind , value = self .memo [k ]
142154 if kind is _fail :
143155 raise value
Original file line number Diff line number Diff line change @@ -97,6 +97,9 @@ def gen():
9797 def gen ():
9898 yield from range (5 )
9999 g3 = gen ()
100+
101+ # Any item that has entered the memo can be retrieved by subscripting.
102+ # len() is the current length of the memo.
100103 test [len (g3 ) == 0 ]
101104 next (g3 )
102105 test [len (g3 ) == 1 ]
@@ -107,8 +110,29 @@ def gen():
107110 test [g3 [0 ] == 0 ]
108111 test [g3 [1 ] == 1 ]
109112 test [g3 [2 ] == 2 ]
113+
114+ # Items not yet memoized cannot be retrieved from the memo.
110115 test_raises [IndexError , g3 [3 ]]
111116
117+ # Negative indices work too, counting from the current end of the memo.
118+ test [g3 [- 1 ] == 2 ]
119+ test [g3 [- 2 ] == 1 ]
120+ test [g3 [- 3 ] == 0 ]
121+
122+ # Counting back past the start is an error, just like in `list`.
123+ test_raises [IndexError , g3 [- 4 ]]
124+
125+ # Slicing is supported.
126+ test [g3 [0 :3 ] == [0 , 1 , 2 ]]
127+ test [g3 [0 :2 ] == [0 , 1 ]]
128+ test [g3 [::- 1 ] == [2 , 1 , 0 ]]
129+ test [g3 [0 ::2 ] == [0 , 2 ]]
130+ test [g3 [2 ::- 2 ] == [2 , 0 ]]
131+
132+ # Out-of-range slices produce the empty list, like in `list`.
133+ test [g3 [3 :] == []]
134+ test [g3 [- 4 ::- 1 ] == []]
135+
112136 with testset ("memoizing a sequence partially" ):
113137 # To do this, build a chain of generators, then memoize only the last one:
114138 evaluations = Counter ()
You can’t perform that action at this time.
0 commit comments