【问题标题】:Trouble understanding classes in python无法理解python中的类
【发布时间】:2020-01-14 21:55:42
【问题描述】:

我是 python 的初学者,但我无法理解类。我有一项任务需要我创建一个应该返回学生信息的类,例如姓名、身份证、年龄和标记。我做了一个类,但输出有问题,并不断收到属性错误:

print("Student: " + self.name + " ID: " + self.ID + " Age: " + self.age + " Mark: " + self.mark)
AttributeError: 'Student' object has no attribute 'age'

我想知道是否有人可以解释我在这里做错了什么,因为我很迷茫。

其余代码:

import random

class Student:
    def __init__(self, name, ID):
        self.name = name
        self.ID = ID

    def setAge(self, age):
        self.age = age
        self.age = random.randint(0, 100)

    def setMarks(self, marks):
        self.marks = marks
        self.marks = random.randint(0, 100)

    def Display(self):
        print("Student: " + self.name + " ID: " + self.ID + " Age: " + self.age + " Mark: " + self.mark)

student = Student("John", "ID123")
student.Display()

【问题讨论】:

  • 您在显示信息之前没有设置年龄或标记...
  • 是的,因为您从未为学生设置年龄。
  • 谢谢你,我刚刚也看到了这个问题,谢谢你的及时回复!
  • 在setAge() 中,self.age = age 有什么意义,因为无论如何你都会立即将self.age 重新分配给一个随机数?
  • 将self.age = None 和self.mark = None 添加到__init__ 函数中。

标签: python python-3.x class methods


【解决方案1】:

你没有调用 student.setMarks() 和 student.setAge() ,所以 marks 和 age 属性还没有在对象中创建。

解决方法是在调用student.Display()之前调用这两个方法

【讨论】:

  • 感谢您的快速回答对我来说非常有效
【解决方案2】:

Python 对象是一个容器,具有您可以设置的属性。如果您不设置属性但尝试读取它,则会收到AttributeError,这意味着您要查找的属性不存在。

目前,student = Student(...) 调用Student.__init__,它分配了对象的name 和ID 属性。您永远不会调用student.setAge 或student.setMarks,因此您的对象的age 和marks 属性永远不会设置并且无法访问。

如果您希望避免出现类似的意外崩溃,通常会在 __init__ 方法中分配默认值。

另一件事是,Python 鼓励使用属性,而不是像 Java 那样拥有 getter 和 setter 方法。属性是类模板中的对象,可以像普通属性一样访问,但允许您运行任意代码来代替访问和赋值运算符。

把所有这些放在一起,你可以写出类似的东西

class Student:
    def __init__(self, name, ID, age=None, marks=None):
        self.name = name
        self.ID = ID
        self.age = random.randint(0, 100) if age is None else age
        self.marks = random.randint(0, 100) if marks is None else marks

    @property
    def marks(self):
        return self._marks

    @marks.setter
    def marks(self, value):
        # Example of a check you could do
        if not isinstance(value, int):
            raise TypeError('Marks must be an integer')

【讨论】:

    【解决方案3】:

    在您的示例中,您尝试在分配之前访问变量。您实际上必须使用参数调用 student.setAge 和 student.setMarks。

    另一方面,在您的函数 setAge 中,您会立即覆盖该值,因此请考虑删除第一个或第二个赋值:

    def setAge(self, age):
        self.age = age # first assignment
        self.age = random.randint(0, 100) # second assignment
    

    【讨论】:

      【解决方案4】:

      age 属性未设置,因为它从未被分配:

      student = Student("John", "ID123")
      student.setAge(30) # John is 30 years old.
      student.Display()
      

      【讨论】:

      • 虽然这解决了问题,而且对于这个作业来说肯定没问题,但我想补充一点,这是一个糟糕的设计:如果每个学生都有年龄,那么它应该是构造函数中的必需参数.
      【解决方案5】:

      def __init__() 像构造函数一样工作。尝试在__init__() 函数中包含age 属性,从__init__() 调用setAge(),或在调用setAge() 之前显式调用Display()。

      祝你好运:)

      【讨论】:

        【解决方案6】:

        更简单的代码版本:

        import random
        
        class Student:
            def __init__(self, name, ID):
                self.name = name
                self.ID = ID
                self.age = random.randint(0, 100)
                self.marks = random.randint(0, 100)
        
            def Display(self):
                print("Student: " + str(self.name) + " ID: " + str(self.ID) + " Age: " + str(self.age) + " Mark: " + str(self.marks))
        
        student = Student("John", "ID123")
        student.Display() 
        

        【讨论】:

          猜你喜欢
          • 2021-07-14
          • 1970-01-01
          • 2016-09-10
          • 2017-03-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-30
          • 1970-01-01
          相关资源
          最近更新 更多