Pergunta

Estou construindo um modelo em Python (3.3.1) para um contrato bastante simples, mas complicado, com fluxos de caixa de longo prazo.O modelo completo é bastante complexo em termos de tempo consumido e por isso decidi tentar traçar um perfil dele.No entanto, estou recebendo respostas diferentes com e sem criação de perfil.

Reduzi o código ao seguinte exemplo:

def generate_cashflows( income ):
    contingent_expense = [1000.0]
    income_cf = [income]
    outgo_cf = [ -0.001 * contingent_expense[0] ]
    bank = [ income_cf[0] + outgo_cf[0] ]

    for t in range(1, 20):
        contingent_expense.append(1000.0)
        income_cf.append( income )
        outgo_cf.append( -contingent_expense[t] * 0.001 )
        bank.append(    bank[t-1] * (1+0.05)**(1/12)
                + income_cf[t]
                + outgo_cf[t]
                )
    return bank[-1]

print(str(generate_cashflows(0)))

Saída:

calum@calum:~/pricing/model$ ./scratch.py 
-20.793337746348953
calum@calum:~/pricing/model$ python -m cProfile scratch.py
-20.0
     80 function calls in 0.000 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.000    0.000 scratch.py:5(<module>)
    1    0.000    0.000    0.000    0.000 scratch.py:5(generate_cashflows)
   76    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    1    0.000    0.000    0.000    0.000 {range}


calum@calum:~/pricing/model$ 

Existe uma explicação simples de por que isso gera uma resposta diferente a cada vez?Eu li o manual, mas não vejo nada óbvio.

Foi útil?

Solução

Primeiro, tentei reproduzir com python3 e executar "python3 scratch.py" e "python3 -m cProfile scratch.py" ambos imprimem -20.7933...na minha máquina.

A razão pela qual -20.0 é retornado em python 2.x é porque o operador de divisão "/" funcionou de maneira diferente em python2.x (http://legacy.python.org/dev/peps/pep-0238/)

Em python2, 1/12 == 0

Em python3, 1/12 == 0,08333333....

Isso significa que em python2 a linha

 bank.append(    bank[t-1] * (1+0.05)**(1/12)

simplifica para

 bank.append(    bank[t-1] * (1+0.05)**(0)

ou

 bank.append(    bank[t-1] * 1

Provavelmente não foi isso que você pretendia.A interpretação python3 provavelmente está correta e a interpretação python2 é bastante inútil.Como observação lateral, alterar (1/12) para (1.0/12) resulta em saída idêntica em python2 e python3 e fará com que seu código retorne a mesma saída com ou sem criação de perfil, mas isso trata o sintoma e não a causa .

Meu melhor palpite sobre por que você está obtendo resultados diferentes com e sem criação de perfil é que você está usando python3 sem criação de perfil e python2 com criação de perfil.Usar a mesma versão do python ao executar seu código com e sem criação de perfil é essencial para obter resultados significativos.

O fato de você estar usando ./scratch.py ​​indica que você provavelmente tem uma linha como

#!/usr/bin/python3

no topo de scratch.py ​​(embora não esteja incluído no código fornecido).Quando você corre

./scratch.py

/usr/bin/python3 é usado para executar o arquivo

Quando você corre

python -m cProfile scratch.py

seu interpretador python padrão é usado para executar o arquivo (que suponho ser python2)

Se você executar "python" na linha de comando (sem quaisquer outros argumentos), provavelmente verá que o interpretador padrão é 2.X.

Portanto, fazer com que seu código retorne uma saída idêntica com e sem criação de perfil deve ser tão simples quanto especificar python3 ao criar o perfil:

 python3 -m cProfile scratch.py
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top