Each of next() and list() iterates over generator with mutable object differently

前端 未结 3 886
孤城傲影
孤城傲影 2021-01-25 10:27
def generator(dct):
    for i in range(3):
        dct[\'a\'] = i
        yield dct

g = generator({\'a\': None})
next(g) # -> {\'a\': 0}
next(g) # -> {\'a\': 1}
n         


        
相关标签:
3条回答
  • 2021-01-25 11:01

    Your generator() generator always yields the same dict object, just with modifications made to it between calls. If you were to, say, change the first next(g) to x = next(g) and then inspect x before and after calling next(g) again, you would see the value of x change across calls, because generator() is always modifying & yielding the same dict object.

    0 讨论(0)
  • 2021-01-25 11:03

    You are looking at intermediate print results. You are modifying a single dictionary, and sharing references to it. You can see the intermediary steps, but that doesn't mean the result is different.

    Store a reference to the object returned from next() and they'll all be the same:

    g = generator({'a': None})
    first = next(g)
    second = next(g)
    third = next(g)
    print(first, second, third) # -> {'a': 2}  {'a': 2}  {'a': 2}
    

    first, second and third are all references to the same object:

    >>> first is second and second is third
    True
    

    You'd see the same thing if you did this in a regular for loop:

    >>> results = []
    >>> d = {'a': None}
    >>> for i in range(3):
    ...     d['a'] = i
    ...     print(d)
    ...     results.append(d)
    ...
    {'a': 0}
    {'a': 1}
    {'a': 2}
    >>> print(results)
    [{'a': 2}, {'a': 2}, {'a': 2}]
    >>> all(d is elem for elem in results)  # all references in results are the same object
    True
    

    The loop prints the dictionary object as it changes each step. The results list contains 3 references to the same object, and each shows the same state once printed at the end.

    0 讨论(0)
  • 2021-01-25 11:18

    They iterate over the iterator identically, but you're checking in at different points. Because dicts are mutable, and you always yield the same dict, you should expect everything you yield to be identical. In your first example, you are looking at the dict as it is changing. Instead consider

    g = generator({'a': None})
    
    a = next(g)
    b = next(g)
    c = next(g)
    
    print(a, b, c)
    # {'a': 2} {'a': 2} {'a': 2}
    
    0 讨论(0)
提交回复
热议问题