关于NoneType的无法解释的错误

时间:2014-05-08 13:20:53

标签: python ide python-3.3 nonetype

我试图访问函数中的全局变量,但它似乎认为它是NoneType。有帮助吗? 该错误似乎相信字典'学生'是NoneType,即使我告诉它,它也不是将它作为全局变量读取。这是我的代码的错误或是这个版本的python的问题,我无法复制任何其他程序的错误(使用2.7-3.3.3版本!)

#Imports
from math import floor
#Global Declarations (for later)
#Functions
def loadData():
    """Loads the students.txt file if it exists."""
    studentsFile = open("students.txt", "r")
    data = studentsFile.read()
    students = exec(data)
    studentsFile.close()
    return students
def fileExists():
    """Checks if the students.txt file exists."""
    try:
        studentsFile = open("students.txt", "r")
        studentsFile.close()
        students = loadData()
    except FileNotFoundError:
        studentsFile = open("students.txt", "w")
        studentsFile.close()
        students = {}
    print(students)
    return students
def saveToFile():
    global students
    studentsFile = open("students.txt", "w")
    studentsFile.write(str(students))
    studentsFile.close()
def gradeCalc(score):
    possibleGrades = {"A*" : [x for x in range(90, 101)], "A" : [x for x in range(80, 90)], "B" : [x for x in range(70, 80)], "C" : [x for x in range(60, 70)], "D" : [x for x in range(50, 60)], "E" : [x for x in range(40, 50)], "F" : [x for x in range(30, 40)], "G" : [x for x in range(20, 30)], "U" : [x for x in range(0, 20)]}
    for key in possibleGrades:
            if int(floor(score)) in possibleGrades[key]:
                grade = key
def studentExists(studentName):
    global students
    print(students)
    print(studentName)
    try:
        testVar = students[studentName]
        return True
    except KeyError:
        return False
def doneTest(studentName, testName):
    try:
        testVar = students[studentName][testName]
        return True
    except KeyError:
        return False
def integerInput(msg):
    while True:
        try:
            integer = int(input(msg))
            return integer
        except ValueError:
            print("Not a whole number.")
def scoreInput():
    while True:
        studentScore = integerInput("Enter the students score: ")
        if studentScore <= 100 and studentScore >= 0:
            break
        else:
            print("Not between (and including) 0 and 100.")
    return studentScore
def getData():
    global students
    quantity = integerInput("How many students do you wish to add? ")
    test = str(input("Please enter a test name: ").lower())
    for i in range(0, quantity):
        name = str(input("Student name: ").title())
        score = scoreInput()
        if studentExists(name) == False:
            students[name] = {}
        students[name][test] = score
        students[name][test+"Grade"]=gradeCalc(score)
def displayData():
    global students
    studentsToDisplay = []
    listOfGrades = []
    print("You must choose a mode. How many students got each grade or the grades for an individual student.")
    mode = input("Please select 'grade' or 'student'").lower()
    if mode == 'grade':
        test = str(input("For which test do you want to access the grades for? ").lower())
        for key in students:
            if doneTest(key, test)==True:
                studentsToDisplay.append(key)
        for item in studentsToDisplay:
            listOfGrades.append(students[item][test+"Grade"])
        print("Grades:\nA*:", ListOfGrades.count("A*"), "\nA:", ListOfGrades.count("A"), "\nB:", ListOfGrades.count("B"), "\nC:", ListOfGrades.count("C"), "\nD:", ListOfGrades.count("D"), "\nE:", ListOfGrades.count("E"), "\nF:", ListOfGrades.count("F"), "\nG:", ListOfGrades.count("G"), "\nU:", ListOfGrades.count("U"))
    elif mode == "student":
        studentName = str(input("Student name: ").title())
        test = str(input("Test name: ").lower())
        if doneTest(studentName, test) == True:
            print(studentName, "got", students[studentName][test], "and this is grade:", students[studentName][test+"Grade"])
def main():
    global students
    students = fileExists()
    while True:
        choice = str(input("Do you want to add students/tests or do you want to review previous data? (accepts 'add' and 'review') ").lower())
        if choice == "add":
            getData()
            saveToFile()
        elif choice == "review":
            displayData()
        else:
            exitChoice = str(input("Do you want to exit? ").lower())
            if exitChoice == "yes" or exitChoice == "y":
                break
main()

我收到此错误:

Traceback (most recent call last):
  File "V:\GCSE 2013\sj.sully\Programme Library\Assessed Tasks and CAT Practice\CAT Practice Scenario 1 Code.py", line 108, in <module>
    main()
  File "V:\GCSE 2013\sj.sully\Programme Library\Assessed Tasks and CAT Practice\CAT Practice Scenario 1 Code.py", line 100, in main
    getData()
  File "V:\GCSE 2013\sj.sully\Programme Library\Assessed Tasks and CAT Practice\CAT Practice Scenario 1 Code.py", line 71, in getData
    if studentExists(name) == False:
  File "V:\GCSE 2013\sj.sully\Programme Library\Assessed Tasks and CAT Practice\CAT Practice Scenario 1 Code.py", line 39, in studentExists
    testVar = students[studentName]
TypeError: 'NoneType' object is not subscriptable

我正在使用python 3.3.0。

1 个答案:

答案 0 :(得分:1)

好吧,如果students为无,那是因为您在使用之前没有定义students

但是使用全局变量来解决这个问题是疯狂的。实际上,使用全局变量是邪恶的,不应该这样做。

Python是一种OOP语言,因此您应该使用正确的工具来完成正确的任务。 对于您的特定用例,您可以使用类,例如:

class StudentsData:
    def __init__(self):
        self.students = []

    def loadData(self):
        pass

    def fileExists(self):
        pass

    def save(self):
        pass

    def scoreInput(self):
        pass

    def display(self):
        pass

但是有些函数不适合在类中使用,例如:

def gradeCalc(score):
    pass

def main():
    pass

我没有给你实现,因为你需要尝试失败来了解如何进行正确的OOP设计。我很确定你也在做计算机编程课程,所以请阅读你关于这个主题的课程! ; - )

编辑:要阅读有关该主题的更多信息,请参阅以下SO答案中的资源列表:

编辑#2:我能想到的唯一例外是“全局是邪恶的”规则,用于声明常量(即你不会修改的变量),所以你可以将它们全部定义在你的一个地方程序。我已经读过人们倾向于使用state / env对象作为全局变量,这可以被视为单例,并且很容易被认为是糟糕的编程。在做这样的事情之前你需要三思而后行,因为经常使用一个类可能是一个更好的解决方案......

另外,如果您阅读python的源代码,您将找到使用全局变量的示例。但它不会是在python中不经意间实现的唯一可怕的东西...