42
def create(ids):
    policy = {
        'Statement': []
    }
    for i in range(0, len(ids), 200):
        policy['Statement'].append({
            'Principal': {
                'AWS': list(map(lambda id: f"arn:aws:iam::{id}:root", ids[i:i + 200]))
            }
        })
    return policy

when I make a function call to this method create({'1','2'}) I get an TypeError: 'set' object is not subscriptable error on line 'AWS': list(map(lambda id: f"arn:aws:iam::{id}:root", ids[i:i + 200])). Coming from a java background, is this somehow related to typecasting? Does the error mean that I'm passing a set data structure to a list function? How could can this be resovled?

4
  • 1
    The problem is sets are unordered therefore do not support indexing and slicing. Why do you have to pass a set to this function? Commented Nov 26, 2019 at 0:24
  • 2
    What's your intent with ids[i:i + 200]? Sets can't be indexed as the error says. Maybe put that into a list first or use islice? Indexing a set is diallowed likely because sets aren't ordered, so the element at any given index is essentially arbitrary. Commented Nov 26, 2019 at 0:25
  • "Does the error mean that I'm passing a set data structure to a list function? " Sort of. Only that there is no such thing as a "list function" in python. Python is a dynamically typed language, but you are passing a set object to a function that will try to index that object, which set objects don't support Commented Nov 26, 2019 at 1:13
  • i dont have control over the inputs. They are sets in order to avoid duplicates. I needed ids[i:i+200] to break the input into chunks while creating new sns statements. The trick was to convert the set into list ([*set, ]) and then iterate. Commented Nov 27, 2019 at 16:16

6 Answers 6

31

As per the Python's Official Documentation, set data structure is referred as Unordered Collections of Unique Elements and that doesn't support operations like indexing or slicing etc.

Like other collections, sets support x in set, len(set), and for x in set. Being an unordered collection, sets do not record element position or order of insertion. Accordingly, sets do not support indexing, slicing, or other sequence-like behavior.

When you define temp_set = {1, 2, 3} it just implies that temp_set contains 3 elements but there's no index that can be obtained

>>> temp_set = {1,2,3}
>>> 1 in temp_set
>>> True
>>> temp_set[0]
>>> Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 3326, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-10-50885e8b29cf>", line 1, in <module>
    temp_set[0]
TypeError: 'set' object is not subscriptable
Sign up to request clarification or add additional context in comments.

1 Comment

it should be temp = [1,2,3] instead of {1,2,3}
13

I faced the same problem when dealing with list in python

In python list is defined with square brackets and not curly brackets

wrong List: {1, 2, 3} (it actually creates a set, not a list)

Right List [1, 2, 3]

This link elaborates more about list:
https://www.w3schools.com/python/python_lists.asp

Comments

3

Like @Carcigenicate says in the comment, sets cannot be indexed due to its unordered nature in Python. Instead, you can use itertools.islice in a while loop to get 200 items at a time from the iterator created from the given set:

from itertools import islice

def create(ids):
    policy = {
        'Statement': []
    }
    i = iter(ids)
    while True:
        chunk = list(islice(i, 200))
        if not chunk:
            break
        policy['Statement'].append({
            'Principal': {
                'AWS': list(map(lambda id: f"arn:aws:iam::{id}:root", chunk))
            }
        })
    return policy

2 Comments

Thank you. That worked. another solution I figured was to simply convert incoming set into list using [*ids, ] and then continue ahead.
usefule also for NLTK routines: from itertools import islice bestwords = set([w for w, s in best]) print(list(islice(bestwords, 10)))
2

If you are lazy:

bob = ["a", "b", "b"]
bob = set(bob)
bob = list(bob)

Then you can deal with it.

1 Comment

This works and is a simple way if you just want to iterate a subset of the set/list and see a sample of what's in it. Can do something like this after converting to a list. for item in bob[0:10]: print(item)
1

If the target is to get the tuple values, one option would be to convert the tuple into a list(as below) and then iterate(fetch the index) over the indexes:

st = {4,5,'c','a',2,'b'}

for i in range(0,len(st)):
    print (str(list(st)[i]))

Comments

0

You may have installed an older version of python (3.6 or older) back when the dictionary data type was NOT ordered in nature (it was unordered in python v3.6 or earlier). So install Python 3.7 or a newer version and you won't face an error.

I ran your code on w3 and it works fine. :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.