El bucle for no funciona dentro de una función de Python

Sep 08 2020

Intento crear una función con un bucle para adentro. El script funciona sin función pero declara que la función de Python no funciona. (El guión original es más largo, pero con esta parte creo que es 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]) El script anterior funciona, no hay problemas hasta aquí. Ahora declaro la función 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])

El segundo problema de demostración de código: 'theta_1 no está definido'

Respuestas

2 SilvioMayolo Sep 08 2020 at 12:21

De la documentación paraexec :

Nota : Los locales predeterminados actúan como se describe para la función locals () a continuación: no se deben intentar modificaciones al diccionario de locales predeterminados. Pase un diccionario local explícito si necesita ver los efectos del código en los locales después de que la función exec () regrese.

Entonces, en esencia, no puede usar execpara meterse con variables locales, por razones de eficiencia del intérprete. La misma restricción no se aplica a los globales, por lo que su primera versión funciona.

En cuanto a qué hacer: bueno, las execllamadas son muy innecesarias. Simplemente ejecute el código Python normalmente, sin las execllamadas complicadas . Honestamente, probablemente también funcionará más rápido. En todos los lugares donde hackea clases de variables con nombres similares, simplemente reemplácelas con una sola matriz o diccionario, según el caso de uso.

2 poproar Sep 08 2020 at 12:22

Parece que podría tratarse de un error de sangría.

Tu primera muestra es

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

mientras tu nueva definición es

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

alrededor de la línea 4