Cómo cambiar las variables introducidas en un bucle for en forma de lista

Estoy escribiendo un progtwig básico en Python que solicita al usuario que ingrese 5 puntajes de prueba. El progtwig luego convertirá cada puntaje de prueba a un punto de calificación (es decir, 4.0, 3.0, 2.0 …), y luego toma el promedio de estos números.

He asignado a cada puntaje de prueba su propia variable, y los estoy introduciendo en un bucle for de la siguiente manera:

for num in [score1, score2, score3, score4, score5]: if num >= 90 print('Your test score is a 4.0) elif num = 80 . . and so on for each grade point. 

Ahora, esto funciona bien para mostrar qué puntaje de cada examen es equivalente a la puntuación. Sin embargo, más adelante en la función necesito calcular el promedio de cada uno de estos valores de puntos de calificación. Por lo tanto, me gustaría asignar un valor de punto de calificación a la variable específica que pasó por el bucle for en ese momento. Entonces, cuando el puntaje 1 se pasa a través del bucle for, y se determina el punto de calificación apropiado, ¿cómo puedo realmente asignar ese punto de calificación al puntaje1, y luego al puntaje2 y así sucesivamente a medida que pasan a través del bucle?

Espero que la pregunta quede clara. Parecería una tontería que Python no tenga este tipo de capacidad, porque de lo contrario, no podría redefinir ninguna variable que pase a través de un bucle for si forma parte de una lista que se está pasando.

“Parece una tontería que Python no tenga este tipo de capacidad, porque de lo contrario no podría redefinir ninguna variable que pase por un bucle for si forma parte de una lista que se está pasando”. – Así es como funcionan la mayoría de los lenguajes de progtwigción. Permitir esta capacidad sería malo porque crearía algo llamado efectos secundarios, que hacen que el código sea obtuso.

Además, este es un error de progtwigción común porque debe mantener los datos fuera de los nombres de las variables : consulte http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html (especialmente la lista de preguntas similares, incluso si no está tratando con variables nombres, al menos estás tratando de lidiar con el espacio de nombres variable). El remedio es trabajar en “un nivel superior”: una lista o conjunto en este caso. Es por esto que su pregunta original no es razonable. (Algunas versiones de python te permitirán hackear el diccionario locals() , pero esto no es compatible y tiene un comportamiento indocumentado y un estilo muy pobre).


Sin embargo, puedes obligar a Python a usar efectos secundarios como los siguientes:

 scores = [99.1, 78.3, etc.] for i,score in enumerate(scores): scores[i] = int(score) 

Lo anterior redondeará las puntuaciones hacia abajo en la matriz de scores . Sin embargo, la forma correcta de hacerlo (a menos que esté trabajando con cientos de millones de elementos) es recrear la matriz de scores manera:

 scores = [...] roundedScores = [int(score) for score in scores] 

Si tienes muchas cosas que quieres hacer para un puntaje:

 scores = [..., ..., ...] def processScores(scores): '''Grades on a curve, where top score = 100%''' theTopScore = max(scores) def processScore(score, topScore): return 100-topScore+score newScores = [processScore(s,theTopScore) for s in scores] return newScores 

sidenote: Si está haciendo cálculos de flotación, debería from __future__ import division o usar python3, o convertir a float(...) explícitamente.


Si realmente desea modificar lo que se pasa, puede pasar en un objeto mutable. Los números que está pasando son instancias de objetos inmutables, pero si, por ejemplo, tuvo:

 class Score(object): def __init__(self, points): self.points = points def __repr__(self): return 'Score({})'.format(self.points) scores = [Score(i) for i in [99.1, 78.3, ...]] for s in scores: s.points += 5 # adds 5 points to each score 

Esta aún sería una forma no funcional de hacer las cosas y, por lo tanto, sería propensa a todos los problemas que causan los efectos secundarios.

 # Take the list of grade as input, assume list is not empty def convertGrade(myGrades): myResult = [] # List that store the new grade for grade in myGrades: gpa = (grade / 20) -1 # Depending on how many deciaml you want gpa = round(gpa, 1) myResult.append(gpa) return myResult # The list of grades, can be more than 5 if you want to grades = [88.3, 93.6, 50.2, 70.2, 80.5] convertedGrades = convertGrade(grades) print(convertedGrades) total = 0 # If you want the average of them for grade in convertedGrades: total += grade # add each grade into the total average = total / len(convertedGrades) print('Average GPA is:', average) 

Creo que esto puede hacer lo que quieras, este tipo de cosas es bastante simple, por lo que python esperaría que lo escribieras tú mismo, no sé si te refieres a que python debería venir con una función de convertidor de GPA, seguramente puedes escribir una fácilmente . Si solo desea el número entero (de lo que no estoy seguro, dado que el GPA generalmente viene con un punto decimal), puede usar int () o redondearlo a 0 antes de agregarlo.

salida:

 [3.4, 3.7, 1.5, 2.5, 3.0] Average GPA is: 2.82 

Primera regla: cuando se trata de un conjunto de elementos similares, no utilice un montón de variables con nombre, use una matriz (lista, conjunto, diccionario, lo que sea más sensato).

Segunda regla: a menos que realmente estés presionado por el espacio, no sobrescribas tus variables de esta manera; estás tratando de hacer que una etiqueta (el nombre de la variable) represente dos cosas diferentes (marca bruta y / o gpa). Esto hace que la depuración sea realmente desagradable.

 def get_marks(): marks = [] while True: inp = raw_input("Type in the next mark (just hit  to quit): ") try: marks.append(float(inp)) except ValueError: return marks def gpa(mark): if mark >= 90.0: return 4.0 elif mark >= 80.0: return 3.0 elif mark >= 70.0: return 2.0 elif mark >= 60.0: return 1.0 else: return 0.0 def average(ls): return sum(ls)/len(ls) def main(): marks = get_marks() grades = [gpa(mark) for mark in marks] print("Average mark is {}".format(average(marks))) print("Average grade is {}".format(average(grades))) if __name__=="__main__": main() 

El problema es que cuando escribes esto:

 for num in [score1, score2, score3, score4, score5]: 

Lo que está sucediendo es que está creando una lista que tiene cinco elementos que están definidos por los valores de puntuación 1 a puntuación 5 en el momento en que comienza a iterar. Cambiar uno de estos elementos no cambia la variable original, porque ha creado una lista que contiene copias de estos valores.

Si ejecuta el siguiente script:

 score1 = 2 score2 = 3 for num in [score1, score2]: num = 1 for num in [score1, score2]: print(num) 

verá que cambiar cada valor en la lista que contiene copias de sus variables reales no cambia realmente los valores de la variable original. Para comprender mejor esto, puede considerar buscar la diferencia entre “pasar por referencia” y “pasar por valor”.

Para este problema en particular, recomiendo ubicar las variables que desea poder modificar en una lista para comenzar, luego iterar sobre esa lista en lugar de una lista que contenga copias de esas variables.