Как изменить переменные, введенные в цикл for в форме списка - PullRequest
7 голосов
/ 01 апреля 2012

Я пишу основную программу на 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 в то время.Итак, когда оценка1 проходит через цикл for и определяется соответствующий балл оценки, как я могу на самом деле назначить этот балл для Score1, а затем позже для Score2 и т. Д., Когда они проходят через цикл?

Надеюсь, это проясняет вопрос.Может показаться глупым, что у Python нет такой возможности, потому что в противном случае вы не сможете переопределить любую переменную, переданную через цикл for, если она является частью списка, через который передается.

Ответы [ 4 ]

12 голосов
/ 01 апреля 2012

"Может показаться глупым, что у 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

sidenote: Если вы делаете вычисления с плавающей запятой, вы должны 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

Это все равно будет нефункциональным способом выполнения действий и, таким образом, будет склонен ко всем проблемам, с которыми сталкиваются-эффекты причина.

2 голосов
/ 02 апреля 2012

Первое правило: при работе с группой похожих элементов, не используйте группу именованных переменных - используйте массив (список, набор, словарь, все, что имеет смысл).

Второе правило: если вы действительно не нажимаете на пробел, не перезаписывайте ваши переменные таким образом - вы пытаетесь заставить одну метку (имя переменной) обозначать две разные вещи (необработанный знак и / или гпа). Это делает отладку очень неприятной.

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()
2 голосов
/ 01 апреля 2012
# 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)

Я думаю, что это может делать то, что вы хотите, такого рода вещи довольно просты, поэтому python будет ожидать, что вы напишите это самостоятельно, я не знаю, имеете ли вы в виду, что python должен иметь функцию конвертера GPA, вы наверняка можете написать легко. Если вам нужно только целое число (в чем я не уверен, поскольку GPA обычно идет с десятичной точкой), то вы можете использовать int () или округлить его до 0, прежде чем добавлять его.

выход:

[3.4, 3.7, 1.5, 2.5, 3.0]
Average GPA is: 2.82
2 голосов
/ 01 апреля 2012

Проблема в том, что когда вы пишете это:

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

происходит то, что вы создаете список, который имеет пять элементов, которые определяются значениями от 1 до 5 в момент начала итерации. Изменение одного из этих элементов не приводит к изменению исходной переменной, поскольку вы создали список, содержащий копии этих значений.

Если вы запустите следующий скрипт:

score1 = 2
score2 = 3

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

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

вы увидите, что изменение каждого значения в списке, содержащем копии ваших реальных переменных, на самом деле не изменяет значения исходной переменной. Чтобы лучше понять это, вы можете рассмотреть разницу между «передачей по ссылке» и «передачей по значению».

Для этой конкретной проблемы я бы порекомендовал сначала поместить в список переменные, которые вы хотите изменить, а затем выполнить итерацию по этому списку, а не по списку, содержащему копии этих переменных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...