Python: Adding element to list while iterating

前端 未结 11 655
太阳男子
太阳男子 2020-12-02 15:37

I know that it is not allowed to remove elements while iterating a list, but is it allowed to add elements to a python list while iterating. Here is an example:



        
11条回答
  •  孤城傲影
    2020-12-02 15:49

    In short: If you'are absolutely sure all new objects fail somecond() check, then your code works fine, it just wastes some time iterating the newly added objects.

    Before giving a proper answer, you have to understand why it considers a bad idea to change list/dict while iterating. When using for statement, Python tries to be clever, and returns a dynamically calculated item each time. Take list as example, python remembers a index, and each time it returns l[index] to you. If you are changing l, the result l[index] can be messy.

    NOTE: Here is a stackoverflow question to demonstrate this.

    The worst case for adding element while iterating is infinite loop, try(or not if you can read a bug) the following in a python REPL:

    import random
    
    l = [0]
    for item in l:
        l.append(random.randint(1, 1000))
        print item
    

    It will print numbers non-stop until memory is used up, or killed by system/user.

    Understand the internal reason, let's discuss the solutions. Here are a few:

    1. make a copy of origin list

    Iterating the origin list, and modify the copied one.

    result = l[:]
    for item in l:
        if somecond(item):
            result.append(Obj())
    

    2. control when the loop ends

    Instead of handling control to python, you decides how to iterate the list:

    length = len(l)
    for index in range(length):
        if somecond(l[index]):
            l.append(Obj())
    

    Before iterating, calculate the list length, and only loop length times.

    3. store added objects in a new list

    Instead of modifying the origin list, store new object in a new list and concatenate them afterward.

    added = [Obj() for item in l if somecond(item)]
    l.extend(added)
    

提交回复
热议问题