简体   繁体   English

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

[英]How to change variables fed into a for loop in list form

I am writing a basic program in Python that prompts the user to enter 5 test scores. 我正在用Python编写一个基本程序,提示用户输入5个测试分数。 The program will then convert each test score to a grade point (ie 4.0, 3.0, 2.0...), and then afterwards take the average of these numbers. 然后程序将每个测试分数转换为分数点(即4.0,3.0,2.0 ......),然后取这些数字的平均值。

I've assigned each test score their own variable, and I'm feeding them into a for loop as follows: 我已经为每个测试分数分配了他们自己的变量,我将它们送入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.

Now, this does fine for displaying what each test score is equivalent to grade point wise. 现在,这可以很好地显示每个测试分数等同于分数点。 However, later in the function I need to calculate the average of each of these grade point values. 但是,稍后在函数中我需要计算每个等级点值的平均值。 So, I'd actually like to assign a grade point value to the specific variable passed through the for loop at that time. 所以,我实际上想要将等级点值分配给当时通过for循环传递的特定变量。 So, when score1 is passed through the for loop, and the appropriate grade point is determined, how can I actually assign that grade point to score1, and then later for score2 and so on as they are passed through the loop? 因此,当score1通过for循环,并且确定了适当的成绩点时,我如何才能将该成绩点实际分配给score1,然后将其分配给score2,等等,因为它们通过循环?

I hope that makes the question clear. 我希望这会使问题清楚。 It would seem silly that Python would not have this kind of capability, because if not you wouldn't be able to redefine any variable passed through a for loop if it is part of a list that is being passed through. Python本身没有这种能力似乎很愚蠢,因为如果不是这样你将无法重新定义通过for循环传递的任何变量,如果它是正在传递的列表的一部分。

"It would seem silly that Python would not have this kind of capability, because if not you wouldn't be able to redefine any variable passed through a for loop if it is part of a list that is being passed through." “Python似乎没有这种能力似乎很愚蠢,因为如果不是这样你将无法重新定义通过for循环传递的任何变量,如果它是正在传递的列表的一部分。” - That's how most programming languages work. - 这就是大多数编程语言的工作方式。 To allow this capability would be bad because it would create something called side-effects, which make code obtuse. 允许这种能力会很糟糕,因为它会产生一种称为副作用的东西,这会使代码变得迟钝。

Additionally this is a common programming pitfall because you should keep data out of variable names : see http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html (especially the list of similar questions; even if you aren't dealing with variables names, you are at least trying to deal with the variable namespace). 此外,这是一个常见的编程缺陷,因为您应该使用变量名称保存数据 :请参阅http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html (特别是类似问题的列表;即使您没有处理变量名字,你至少试图处理变量名称空间)。 The remedy is to work at "one level higher": a list or set in this case. 补救措施是在“更高一级”工作:在这种情况下的列表或集合。 This is why your original question is not reasonable. 这就是你原来的问题不合理的原因。 (Some versions of python will let you hack the locals() dictionary, but this is unsupported and undocumented behavior and very poor style.) (某些版本的python会让你破解locals()字典,但这是不受支持和无证件的行为和非常糟糕的风格。)


You can however force python to use side-effects like so: 但是你可以强制python使用这样的副作用:

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

the above will round scores down in the scores array. 以上将在scores数组中将得分降低。 The right way to do this however (unless you are working with hundreds of millions of elements) is to recreate the scores array like so: 然而, 正确的方法 (除非你正在使用数以亿计的元素)是重新创建scores数组,如下所示:

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

If you have many things you want to do to a score: 如果你有很多想做的事情:

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: If you're doing float calculations, you should from __future__ import division or use python3, or cast to float(...) explicitly. 旁注:如果你正在进行浮点计算,你应该from __future__ import division或使用python3,或者显式地转换为float(...)


If you really want to modify what is passed in, you can pass in a mutable object. 如果你真的想修改传入的内容,可以传入一个可变对象。 The numbers you are passing in are instances of immutable objects, but if for example you had: 您传入的数字是不可变对象的实例,但例如,如果您有:

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

This would still be a non-functional way to do things, and thus prone to all the issues that side-effects cause. 这仍然是一种非功能性的做事方式,因此容易产生副作用引起的所有问题。

First rule: when dealing with a bunch of similar items, don't use a bunch of named variables - use an array (list, set, dictionary, whatever makes the most sense). 第一条规则:当处理一堆类似的项目时, 不要使用一堆命名变量 - 使用数组(列表,集合,字典,最有意义的东西)。

Second rule: unless you are really pressed for space, don't overwrite your variables this way - you are trying to make one label (the variable name) stand for two different things (raw mark and/or gpa). 第二条规则:除非你真的要求空间, 否则不要用这种方式覆盖你的变量 - 你试图让一个标签(变量名)代表两种不同的东西(原始标记和/或gpa)。 This makes debugging really nasty. 这使调试真的很讨厌。

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()

The problem is that when you write this: 问题是当你写这个:

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

what is happening is that you are creating a list which has five elements which are defined by the values of score1 through score 5 at the time you start iterating. 发生的事情是你创建的列表有五个元素,这些元素在你开始迭代时由score1到score5的值定义。 Changing one of these elements does not change the original variable, because you've created a list containing copies of these values. 更改其中一个元素不会更改原始变量,因为您已创建包含这些值副本的列表。

If you run the following script: 如果您运行以下脚本:

score1 = 2
score2 = 3

for num in [score1, score2]:
    num = 1

for num in [score1, score2]:
    print(num)

you'll see that changing each value in the list containing copies of your actual variables does not actually change the original variable's values. 您将看到更改包含实际变量副本的列表中的每个值实际上并不会更改原始变量的值。 To get a better understanding of this, you might consider looking up the difference between "pass by reference" and "pass by value". 为了更好地理解这一点,您可以考虑查找“按引用传递”和“按值传递”之间的区别。

For this particular problem, I'd recommend placing the variables you want to be able to modify in a list to begin with, then iterating over that list rather than a list containing copies of those variables. 对于这个特殊问题,我建议将您希望能够修改的变量放在列表中,然后迭代该列表而不是包含这些变量副本的列表。

# 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)

I think this might do what you want, this sort of things is quite simple, so python would expect you to write it yourself, I don't know if you mean python should come with a GPA converter function, you can surely write one easily. 我觉得这可能会做你想要的,这种事情很简单,所以python会期望你自己写,我不知道你是不是意味着python应该带有GPA转换器功能,你一定可以轻松写一个。 If you want whole number only, (which I am not sure, since GPA usually comes with decimal point), then you can use int(), or round it to 0 before you append it. 如果你只想要整数,(我不确定,因为GPA通常带有小数点),那么你可以使用int(),或者在你追加之前将它四舍五入为0。

output: 输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM