Your x value is is a generator object, which is an Iterator: it generates values in order, as they are requested by a for loop or by calling next(x).
You are trying to access it as though it were a list or other Sequence type, which let you access arbitrary elements by index as x[p + 1].
If you want to look up values from your generator’s output by index, you may want to convert it to a list:
x = list(x)
This solves your problem, and is suitable in most cases. However, this requires generating and saving all of the values at once, so it can fail if you’re dealing with an extremely long or infinite list of values, or the values are extremely large.
If you just needed a single value from the generator, you could instead use itertools.islice(x, p) to discard the first p values, then next(...) to take the one you need. This eliminate the need to hold multiple items in memory or compute values beyond the one you’re looking for.
import itertools
result = next(itertools.islice(x, p))
In Python, you cannot access values inside a generator object using indexing syntax.
A generator function returns a generator object, an iterator containing a sequence of values. We can access the values in a generator object using a for loop or by calling next().
We can solve this error by converting the generator object to a list using the built-in list() method.
For example,
# A generator function
def generator_func():
yield 1
yield 2
yield 3
# x is a generator object
x = list(generator_func())
print(x[0])
This tutorial will go through how to solve the error with code examples.
Table of contents
- TypeError: ‘generator’ object is not subscriptable
- Example
- Solution
- Summary
TypeError: ‘generator’ object is not subscriptable
Let’s break up the error message to understand what the error means. TypeError occurs whenever you attempt to use an illegal operation for a specific data type. The part “generator object” tells us the error concerns an illegal operation for the generator object.
The part “is not subscriptable” tells us we cannot access an element of the generator object using the subscript operator, which is square brackets [].
A subscriptable object is a container for other objects and implements the __getitem__() method. Examples of subscriptable objects include strings, lists, tuples, and dictionaries.
We can check if an object implements the __getitem__() method by listing its attributes with the dir function. Let’s call the dir function and pass a generator object and a str object to see their attributes.
# A generator function
def generator_func():
yield 1
yield 2
yield 3
x = generator_func()
print(dir(x))
['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
We can see that __getitem__ is not present in the list of attributes for the generator object.
string = "Python" print(dir(string))
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
We can see that __getitem__ is present in the list of attributes for the str object.
If we want to check if a specific attribute belongs to an object, we can check for membership using the in operator.
# A generator function
def generator_func():
yield 1
yield 2
yield 3
x = generator_func()
# Check type of object
print(type(x))
# Check membership of attribute
print('__getitem__' in dir(x))
<class 'generator'> False
The variable x is an object of the generator class. We can see that __getitem__ is not an attribute of the generator class.
string = "Python"
print(type(string))
print('__getitem__' in dir(string))
<class 'str'> True
We can see that __getitem__ is an attribute of the str class.
Example
Let’s look at an example of trying to access an element of a generator object using indexing. First, we will create the generator() function.
Generator functions allow us to declare a function that behaves like an iterator. We use a yield statement rather than a return statement in a generator function.
def generator_func():
yield 2
yield 3
yield 8
Next, we will assign the generator object returned by the generator function to a variable,
x = generator_func()
Next, we will attempt to access the first item in the generator object using indexing syntax.
first_num = x[0] print(first_num)
Let’s run the code to see what happens:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [41], in <cell line: 1>()
----> 1 first_num = x[0]
2 print(first_num)
TypeError: 'generator' object is not subscriptable
The error occurs because the x variable is a generator object, which is an Iterator. Iterators generate values in order as requested by a for loop or by calling next(). We are trying to access values in the object as though it were a list or another subscriptable object.
Solution
We can solve this error by converting the generator object to a list using the built-in list() method.
Let’s look at the revised code:
def generator_func():
yield 2
yield 3
yield 8
x = list(generator_func())
first_num = x[0]
print(first_num)
Let’s run the code to get the result:
2
The first item in the generator object is the number 2.
Summary
Congratulations on reading to the end of this tutorial!
For further reading on not subscriptable errors, go to the articles:
- How to Solve Python TypeError: ‘zip’ object is not subscriptable
- How to Solve Python TypeError: ‘dict_items’ object is not subscriptable
- How to Solve Python TypeError: ‘datetime.datetime’ object is not subscriptable
To learn more about Python for data science and machine learning, you can go to the online courses page on Python for the most comprehensive courses.
Have fun and happy researching!
I also get this error even after doing pip install networkx==1.11:
TypeError Traceback (most recent call last)
in ()
4 algo=tpe.suggest,
5 max_evals=2,
—-> 6 trials=trials)
7
8 print(best)
~/.envs/YM_py3.5/lib/python3.5/site-packages/hyperopt/fmin.py in fmin(fn, space, algo, max_evals, trials, rstate, allow_trials_fmin, pass_expr_memo_ctrl, catch_eval_exceptions, verbose, return_argmin)
305 verbose=verbose,
306 catch_eval_exceptions=catch_eval_exceptions,
—> 307 return_argmin=return_argmin,
308 )
309
~/.envs/YM_py3.5/lib/python3.5/site-packages/hyperopt/base.py in fmin(self, fn, space, algo, max_evals, rstate, verbose, pass_expr_memo_ctrl, catch_eval_exceptions, return_argmin)
633 pass_expr_memo_ctrl=pass_expr_memo_ctrl,
634 catch_eval_exceptions=catch_eval_exceptions,
—> 635 return_argmin=return_argmin)
636
637
~/.envs/YM_py3.5/lib/python3.5/site-packages/hyperopt/fmin.py in fmin(fn, space, algo, max_evals, trials, rstate, allow_trials_fmin, pass_expr_memo_ctrl, catch_eval_exceptions, verbose, return_argmin)
312
313 domain = base.Domain(fn, space,
—> 314 pass_expr_memo_ctrl=pass_expr_memo_ctrl)
315
316 rval = FMinIter(algo, domain, trials, max_evals=max_evals,
~/.envs/YM_py3.5/lib/python3.5/site-packages/hyperopt/base.py in init(self, fn, expr, workdir, pass_expr_memo_ctrl, name, loss_target)
784 before = pyll.dfs(self.expr)
785 # — raises exception if expr contains cycles
—> 786 pyll.toposort(self.expr)
787 vh = self.vh = VectorizeHelper(self.expr, self.s_new_ids)
788 # — raises exception if v_expr contains cycles
~/.envs/YM_py3.5/lib/python3.5/site-packages/hyperopt/pyll/base.py in toposort(expr)
713 G.add_edges_from([(n_in, node) for n_in in node.inputs()])
714 order = nx.topological_sort(G)
—> 715 assert order[-1] == expr
716 return order
717
TypeError: ‘generator’ object is not subscriptable
ВЕСЬ Ваш x значение — это объект-генератор, который является Iterator: он генерирует значения по порядку, так как они запрашиваются for цикл или позвонив next(x).
Вы пытаетесь получить к нему доступ, как если бы это был список или другой Sequence type, который позволяет вам получать доступ к произвольным элементам по индексу как x[p + 1].
Если вы хотите искать значения из вывода вашего генератора по индексу, вы можете преобразовать его в список:
x = list(x)
Это решает вашу проблему и подходит в большинстве случаев. Однако это требует генерации и сохранения всех значений сразу, поэтому может произойти сбой, если вы имеете дело с очень длинным или бесконечным списком значений или значения очень большие.
Если вам просто нужно одно значение из генератора, вы можете вместо этого использовать itertools.islice(x, p) отказаться от первого p значения, то next(...) взять тот, который вам нужен. Это избавляет от необходимости хранить в памяти несколько элементов или вычислять значения, выходящие за рамки того, что вы ищете.
import itertools
result = next(itertools.islice(x, p))