Является ли x в цикле «для x в словаре» глобальной переменной?

#python #python-3.x

Вопрос:

Я создаю простую программу в качестве практики на Python [3.9] (код ниже).

PyCharm показывает предупреждение «Предупреждение: имя тени» тема «из внешней области», когда я определяю переменную цикла for, как subject в (в разделе «Печать оценок»).

Полный код:

 class Student:

    grades = {}

    def __init__(self, name=""):
        self.name = name

    def get_average(self):
        total = 0
        for subject in self.grades:
            total  = self.grades[subject]

        return total / len(self.grades.keys())

    def set_grade(self, subject, score):

        subject = subject.lower()

        if not isinstance(score, int):
            return None

        self.grades[subject] = int(score)

        return self.grades[subject]

    def get_grade(self, subject):
        return self.grades.get(subject)

    def get_subjects(self):
        return list(self.grades.keys())


student = Student("My Name")
student.set_grade("Mathematics", 98)
student.set_grade("english", 95)
student.set_grade("ScieNce", 93)
    
print("Name: "   student.name)
    
print("Subjects: "   str(student.get_subjects()))
    
print("Grades:")
for subject in student.get_subjects():
    print(str(subject), student.get_grade(subject))

print("Average: "   str(student.get_average()))
 

Вопрос:
Является subject ли в

 for subject in student.get_subjects():
    print(str(subject), student.get_grade(subject))
 

глобальная переменная?

Если нет, то почему PyCharm показывает мне эту ошибку и как я могу улучшить свой код, чтобы он не отображался?

Примечание: Предположим, что код внутри класса имеет правильный отступ. Код был переформатирован при вставке кода.

Комментарии:

1. Не могли бы вы исправить отступ?

2. @Kimley Я отредактировал код в вашем вопросе — я добавил отсутствующий отступ там, где, по моему мнению, это необходимо. Можете ли вы подтвердить, что это правильно?

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

4. for subject in student.get_subjects() создает глобальную переменную student , проверьте по globals() . Теперь, когда вы снова определяете students класс, он предупреждает вас о том, что вы, возможно, захотите использовать глобальную переменную, объявив ее глобальной, поскольку в python изменение переменной по умолчанию не является глобальным

5. спасибо @PaulM. да, это правильно

Ответ №1:

Ваш код верен и subject является локальной переменной, но PyCharm анализирует всю страницу — поэтому у вас есть такое предупреждение. Вы можете изменить имя переменной

 for sub in student.get_subjects():
    print(str(sub), student.get_grade(sub))
 

Или вы можете создать файл с именем student и поместить туда свой студенческий код

 from student import Student


student = Student("Kimley Rafallo")
student.set_grade("Mathematics", 98)
student.set_grade("english", 95)
student.set_grade("ScieNce", 93)

print("Name: "   student.name)

print("Subjects: "   str(student.get_subjects()))

print("Grades:")
for sub in student.get_subjects():
    print(str(sub), student.get_grade(sub))

print("Average: "   str(student.get_average()))
 

Комментарии:

1. Я понимаю. Спасибо тебе за это.

2. @Kimley отметьте ответ как полезный — если сможете)

Ответ №2:

Python не имеет области действия блока, поэтому переменная, подобная subject в цикле for subject in student.get_subjects(): , принадлежит тому модулю или функции, которые заключают цикл. В этом случае ваш цикл находится в глобальной области модуля, поэтому subject становится глобальной переменной.

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

 def main():
    student = Student("Kimley Rafallo")
    student.set_grade("Mathematics", 98)
    student.set_grade("english", 95)
    student.set_grade("ScieNce", 93)
    
    print("Name: "   student.name)
    
    print("Subjects: "   str(student.get_subjects()))
    
    print("Grades:")
    for subject in student.get_subjects():
        print(str(subject), student.get_grade(subject))
    
    print("Average: "   str(student.get_average()))

if __name__ == '__main__':
    main()