O loop for não funciona dentro de uma função python

Sep 08 2020

Tento criar uma função com um loop para dentro. O script funciona sem função, mas declara que a função python não funciona. (O roteiro original é mais longo, mas com essa parte acho que é o suficiente)

import numpy as np
import math as mt
from sympy import*
import fractions
init_printing(use_latex='mathjax')
PHnumbers=4
PHnumbers2=2
statetype= 1
for d in range(1,9):                                                                                                     
    modes=d+1
    if statetype==1:                                                                                                 
       comb=modes 
    elif statetype==2:
        comb=int((modes*(modes+1))/2)
    exec(f'Phases{d}=[]'), exec(f'Phasesv{d}=[]')
    for i in range(modes):
        exec(f'theta_{i+1}= symbols(\'theta_{i+1}\', real=True)')                                                          
        exec(f'Phases{d}.append(globals()[\'\'.join([\'theta_\',str(i+1)])])') 
        exec(f'Phasesv{d}.append(globals()[\'\'.join([\'theta_\',str(i+1)])])')                                           
        exec(f'v{i+1}=[[0]]*modes')                                                                                        
        exec(f'Phasesv{d}[0]*=0')
    for i in range(modes):
        exec(f'globals()[\'\'.join([\'v\',str(i+1)])][i]=[PHnumbers*diff(Phasesv{d}[i],Phases{d}[i])]')                     
    conteo = d
    for j in range(modes):
        for i in range(modes):
            if j<i:
                conteo = conteo + 1
                exec(f'v{conteo+1}=[[0]]*modes')
                exec(f'globals()[\'\'.join([\'v\',str(conteo+1)])][i]=[PHnumbers2*diff(Phasesv{d}[i],Phases{d}[i])]')  
                exec(f'globals()[\'\'.join([\'v\',str(conteo+1)])][j]=[PHnumbers2*diff(Phasesv{d}[j],Phases{d}[j])]')  
exec(f'Vec{d}=[]'),exec(f'Coeff{d}=[]'), exec(f'Nii{d}=[]'), exec(f'Nij{d}=[]')
for i in range(comb):
        exec(f'Vec{d}.append(globals()[\'\'.join([\'v\',str(i+1)])])')

for i in range (len (Vec4)): print (Vec4 [i]) O script anterior funcionou, sem problemas até aqui. Agora declaro a função python:

def metro(PHnumbers):                                                                                                           
    statetype=1
    PHnumbers2=2
    for d in range(1,9):                                                                                                     
        modes=d+1
    if statetype==1:                                                                                                 
        comb=modes 
    elif statetype==2:
        comb=int((modes*(modes+1))/2)
    exec(f'Phases{d}=[]'), exec(f'Phasesv{d}=[]')
    for i in range(modes):
        exec(f'theta_{i+1}= symbols(\'theta_{i+1}\', real=True)')                                                          
        exec(f'Phases{d}.append(globals()[\'\'.join([\'theta_\',str(i+1)])])') 
        exec(f'Phasesv{d}.append(globals()[\'\'.join([\'theta_\',str(i+1)])])')                                           
        exec(f'v{i+1}=[[0]]*modes')                                                                                        
        exec(f'Phasesv{d}[0]*=0')
    for i in range(modes):
        exec(f'globals()[\'\'.join([\'v\',str(i+1)])][i]=[PHnumbers*diff(Phasesv{d}[i],Phases{d}[i])]')                     
    conteo = d
    for j in range(modes):
        for i in range(modes):
            if j<i:
                conteo = conteo + 1
                exec(f'v{conteo+1}=[[0]]*modes')
                exec(f'globals()[\'\'.join([\'v\',str(conteo+1)])][i]=[PHnumbers2*diff(Phasesv{d}[i],Phases{d}[i])]')  
                exec(f'globals()[\'\'.join([\'v\',str(conteo+1)])][j]=[PHnumbers2*diff(Phasesv{d}[j],Phases{d}[j])]')  
exec(f'Vec{d}=[]'),exec(f'Coeff{d}=[]'), exec(f'Nii{d}=[]'), exec(f'Nij{d}=[]')
for i in range(comb):
        exec(f'Vec{d}.append(globals()[\'\'.join([\'v\',str(i+1)])])')
for i in range(len(Vec4)):
    print(Vec4[i])

O segundo código mostra o problema: 'theta_1 is not defined'

Respostas

2 SilvioMayolo Sep 08 2020 at 12:21

Da documentação paraexec :

Nota : Os locais padrão agem conforme descrito para a função locals () abaixo: modificações no dicionário de locais padrão não devem ser tentadas. Passe um dicionário de locais explícito se você precisar ver os efeitos do código nos locais após o retorno da função exec ().

Então, em essência, você não pode execmexer com variáveis ​​locais, por razões de eficiência do intérprete. A mesma restrição não se aplica a globais, e é por isso que sua primeira versão funciona.

Quanto ao que fazer: bem, as execligações são altamente desnecessárias. Simplesmente execute o código Python normalmente, sem as execchamadas confusas . Sinceramente, provavelmente será mais rápido também. Em todos os lugares onde você hackear classes de variáveis ​​com nomes semelhantes, apenas substitua-as por um único array ou dicionário, dependendo do caso de uso.

2 poproar Sep 08 2020 at 12:22

Parece que pode ser um erro de recuo.

Sua primeira amostra é

for d in range(1,9):                                                                                                     
    modes=d+1
    if statetype==1: 

enquanto sua nova definição é

for d in range(1,9):                                                                                                     
    modes=d+1
if statetype==1:    

em torno da linha 4