The generator does not close the data as expected

Sorry if the title is poorly worded, I'm not sure how to express it. I have a function that basically iterates over the second dimension of a two-dimensional iterative. The following is simple playback:

words = ['ACGT', 'TCGA']

def make_lists():
    for i in range(len(words[0])):
        iter_ = iter([word[i] for word in words])
        yield iter_

lists = list(make_lists())

for list_ in lists:
    print(list(list_))

The execution of these outputs:

['A', 'T']
['C', 'C']
['G', 'G']
['T', 'A']

I would like to get generators instead of evaluating wordsin case it is wordsvery long, so I tried the following:

words = ['ACGT', 'TCGA']

def make_generators():
    for i in range(len(words[0])):
        gen = (word[i] for word in words)
        yield gen

generators = list(make_iterator())

for gen in generators:
    print(list(gen))

However, working outputs:

['T', 'A']
['T', 'A']
['T', 'A']
['T', 'A']

I don’t know exactly what is going on. I suspect that this has something to do with understanding the generator without covering its scope when they yield, so they all share. If I create generators inside a separate function and get a return from this function, it works.

+4
1

i , , .. 3. , i, i, . , - :

def make_iterator():
    for i in range(len(words[0])):
        gen = (word[i] for word in words)
        yield gen
    i = 0  # Modified the value of i 

:

['A', 'T']
['A', 'T']
['A', 'T']
['A', 'T']

, , i . ( Python 3, , )

, i :

words = ['ACGT', 'TCGA']

def make_iterator():
    for i in range(len(words[0])):
        # default argument value is calculated at the time of
        # function creation, hence for each generator it is going
        # to be the value at the time of that particular iteration  
        def inner(i=i):
            return (word[i] for word in words)
        yield inner()

generators = list(make_iterator())

for gen in generators:
    print(list(gen))

:

+3

Source: https://habr.com/ru/post/1607126/


All Articles