Непонимание классов в python - PullRequest
0 голосов
/ 15 января 2020

Я новичок в 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()

Ответы [ 5 ]

1 голос
/ 15 января 2020

Python объекты - это контейнер, атрибуты которого вы можете установить. Если вы не устанавливаете атрибут, но пытаетесь прочитать его, вы получаете AttributeError, что означает, что искомый атрибут не существует.

В настоящее время student = Student(...) вызывает Student.__init__, что назначает атрибут name и ID объекта. Вы никогда не вызываете student.setAge или student.setMarks, поэтому атрибуты age и marks вашего объекта никогда не устанавливаются и не могут быть доступны.

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

Другое дело, что вместо использования методов получения и установки, как Java, например, Python поощряет использование свойств. Свойства - это объекты в шаблоне класса, к которым можно обращаться как к обычному атрибуту, но они позволяют запускать произвольный код вместо операторов доступа и присваивания.

Собрав все это вместе, вы могли бы написать что-то вроде

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')
1 голос
/ 15 января 2020

Вы не вызывали student.setMarks() и student.setAge(), поэтому атрибуты marks и age в объекте еще не созданы.

Решение состоит в том, чтобы вызвать эти два метода перед вызовом student.Display()

1 голос
/ 15 января 2020

В вашем примере вы пытаетесь получить доступ к переменной, перед присваиванием. На самом деле вам придется вызывать student.setAge и student.setMarks с аргументами.

С другой стороны, в вашей функции setAge вы мгновенно перезаписываете значение, поэтому рассмотрите возможность удаления первого или второго назначения:

def setAge(self, age):
    self.age = age # first assignment
    self.age = random.randint(0, 100) # second assignment
0 голосов
/ 15 января 2020

def __init__() работает как конструктор. Попробуйте включить атрибут age в функцию __init__(), вызовите setAge() из __init__() или setAge() явно перед вызовом Display().

Удачи:)

0 голосов
/ 15 января 2020

Атрибут age не задан, поскольку он никогда не назначался:

student = Student("John", "ID123")
student.setAge(30) # John is 30 years old.
student.Display()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...