Pergunta

Olá a todos, eu estava trabalhando em um gerador de recursiva para criar o fixo inteiro partições de um número e eu estava confuso por um problema de delimitação do âmbito.

O código é semelhante a esse trecho.

def testGen(a,n):
    if n <= 1:
        print('yield', a)
        yield a
    else:
        for i in range(2):
            a[i] += n
            for j in testGen(a,n-i-1):
                yield j

A minha confusão é ilustrado abaixo.

>>> list(testGen([1,2],4))
yield [10, 2]
yield [10, 4]
yield [10, 7]
yield [12, 11]
yield [12, 13]
[[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]]

Eu posso obter a resposta certa simplesmente usando uma cópia da matriz (por exemplo, passando em a[:] para a chamada recursiva), mas eu ainda não entendo o comportamento acima. Por que são as declarações de impressão e valores de rendimento diferentes?

Foi útil?

Solução

A declaração de impressão exibe a lista nesse ponto específico no tempo. Seu código altera a lista como você executá-lo, por isso, o tempo que você examinar a lista no final, você vê o seu valor depois.

Você pode observar esse, percorrendo:

>>> g = testGen([1,2],4)
>>> g.next()
('yield', [10, 2])   # note brackets in print statement because I'm on python 2.5
[10, 2]
>>> g.next()
('yield', [10, 4])
[10, 4]
>>> g.next()
('yield', [10, 7])
[10, 7]
>>> g.next()
('yield', [12, 11])
[12, 11]
>>> g.next()
('yield', [12, 13])
[12, 13]

Outras dicas

Eu acho que você está transformando a matriz, então quando você imprimi-lo tem um valor particular, então a próxima vez que você imprimi-lo tem realmente atualizou o valor, e assim por diante. No final, você tem 5 referências para a mesma matriz, então é claro que você tem o mesmo valor de 5 vezes.

As listas são objetos mutáveis, se você passar em uma lista, e as executa gerador operações no local nessa lista, então, finalmente, todas as referências à lista irá apontar para a mesma lista.

O impressão e rendimento declarações são diferentes, porque você só tem uma declaração de impressão enquanto você tem 2 rendimentos. Tente isto:

def testGen(a,n):
    if n <= 1:
        print('yield', a)
        yield a
    else:
        for i in range(2):
            a[i] += n
            for j in testGen(a,n-i-1):
                print('yield', j)
                yield j

>>> list(testGen([1,2],4))
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 7])
('yield', [10, 7])
('yield', [10, 7])
('yield', [12, 11])
('yield', [12, 11])
('yield', [12, 11])
('yield', [12, 13])
('yield', [12, 13])
('yield', [12, 13])
[[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]]

Você vai ver que os últimos rendimentos são as suas respostas, porque você foi passando ao redor da mesma lista em vez de fazer uma cópia.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top