The following is a snippet of code from CS50P.
I don't understand how it works and cannot seem to find an adequate explanation.
Firstly, as soon as the Student constructor is called with user inputted arguments name and home, the init method is subsequently called with the same arguments. Now, it is unclear to me what exactly happens in the following two lines:
self.name = name
self.house = house
Essentially, from what I understand, since "name" in self.name matches with name(self, name) under @name.setter, self.name = name calls name(self, name) with the value of name as the argument. No return value is given, but instead, a new instance variable, namely _name is created, which is assigned to the same value of name (if the error check is passed). I do not understand why it is necessary to create this new variable with the underscore at the beginning in place of name. Also, I would like a more "under the hood" explanation of what "self.name" really does because I think my understanding is quite limited and might even be incorrect.
In addition, I was introduced to the idea of getters and setters out of nowhere, apart from being given the explanation that they allow user data to be validated when attribute values are set, whether they be set in the init function or outside of the class altogether. However, what do they really mean "under the hood" and what is the significance of the setter having a reference to the instance variable, but not the getter? Where do the names "property" and "name.setter" come from, and what about the "@" at the beginning? It's my first time seeing this syntax, so it is quite confusing and ilogical to me.
class Student:
def __init__(self, name, house):
self.name = name
self.house = house
def __str__(self):
return f"{self.name} from {self.house}"
@property
def name(self):
return self._name
@name.setter
def name(self, name):
if not name:
raise ValueError("Invalid name")
self._name = name
@property
def house(self):
return self._house
@house.setter
def house(self, house):
if house not in ["Gryffindor", "Hufflepuff", "Ravenclaw", "Slytherin"]:
raise ValueError("Invalid house")
self._house = house
def main():
student = get_student()
print(student)
def get_student():
name = input("Name: ")
house = input("House: ")
return Student(name, house)
if __name__ == "__main__":
main()