如何更改以列表形式输入 for 循环的变量

新手上路,请多包涵

我正在用 Python 编写一个基本程序,提示用户输入 5 个测试分数。然后程序会将每个测试分数转换为成绩点(即 4.0、3.0、2.0…),然后取这些数字的平均值。

我已经为每个测试分数分配了自己的变量,并将它们输入到 for 循环中,如下所示:

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

现在,这可以很好地显示每个考试成绩相当于什么成绩点。但是,稍后在函数中我需要计算每个成绩点值的平均值。因此,我实际上想为当时通过for循环传递的特定变量分配一个成绩点值。因此,当 score1 通过 for 循环传递并确定了适当的成绩点时,我如何才能将该成绩点实际分配给 score1,然后再分配给 score2 等等,因为它们通过循环传递?

我希望这可以使问题清楚。 Python 没有这种能力似乎很愚蠢,因为如果没有,你将无法重新定义通过 for 循环传递的任何变量,如果它是正在传递的列表的一部分。


不仅列表“中”的变量(列表实际上只存储值)被更新,而且列表根本没有被这个过程更新。请参阅 为什么不分配给循环变量修改原始列表?如何循环分配回列表? 对于那个版本的问题。

原文由 Dustin Burns 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 650
2 个回答

“如果 Python 没有这种能力,这似乎很愚蠢,因为如果没有,你将无法重新定义通过 for 循环传递的任何变量,如果它是正在传递的列表的一部分。” - 这就是大多数编程语言的工作方式。允许这种能力是不好的,因为它会产生所谓的副作用,使代码变得迟钝。

此外,这是一个常见的编程陷阱,因为您应该 将数据排除在变量名称之外:请参阅 http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html (尤其是类似问题的列表;即使您不处理变量名称,您至少要尝试处理变量名称空间)。补救措施是在“更高一级”工作:在这种情况下是列表或集合。这就是为什么你原来的问题是不合理的。 (某些版本的 python 会让你破解 locals() 字典,但这是不受支持和未记录的行为,而且风格很差。)


但是,您可以强制 python 使用像这样的副作用:

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

以上将在 scores 数组中舍入分数。然而,执行此操作的 正确方法(除非您正在处理数亿个元素)是重新创建 scores 数组,如下所示:

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

如果你有很多事情想做一个分数:

 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

旁注:如果您正在进行浮点计算,您应该 from __future__ import division 或使用 python3,或显式转换为 float(...)


如果你真的想修改传入的内容,你可以传入一个可变对象。您传入的数字是不可变对象的实例,但是例如您有:

 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

这仍然是一种非功能性的做事方式,因此容易出现副作用引起的所有问题。

原文由 ninjagecko 发布,翻译遵循 CC BY-SA 3.0 许可协议

第一条规则:在处理一堆相似的项目时, 不要 使用一堆命名变量——使用数组(列表、集合、字典,任何最有意义的)。

第二条规则:除非你真的迫于空间, 否则不要 以这种方式覆盖你的变量 - 你试图让一个标签(变量名)代表两种不同的东西(原始标记和/或 gpa)。这使得调试非常讨厌。

 def get_marks():
    marks = []
    while True:
        inp = raw_input("Type in the next mark (just hit <Enter> 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()

原文由 Hugh Bothwell 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题