Confused with: course_running.add_student(self) [duplicate] - python

This question already has answers here:
Python - Classes and OOP Basics
(6 answers)
Closed 5 years ago.
Could anyone help with my understanding, please? I don't understand what is happening with this line or why it works : course_running.add_student(self).
I thought this was an OOP concept but could anyone help make this clearer?
class Student:
def __init__(self, name, student_number):
self.name = name
self.student_number = student_number
self.classes = []
def enrol(self, course_running):
self.classes.append(course_running)
course_running.add_student(self)
class CourseRunning:
def __init__(self, course, year):
self.course = course
self.year = year
self.students = []
def add_student(self, student):
self.students.append(student)

course_running is an object of class CourseRunning and course_running.add_student(self) is calling a method of it's class named add_student which is appending the student to students list.

Your enrol() function in the Student class is taking two parameters: self and course_running.
self is the instance of your current class (Student).
That's why in your add_student() function (which takes also two parameters: self (the current instance of the CourseRunning class) and student (which is simply an instance of a Student)).
That's why you can pass the self from enrol() as student in add_student().

Related

Object instance in loop Python Classes [duplicate]

This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 3 years ago.
Hello Just curious on why the second instance already gets the category that was added in the first instance creation. How can i fix it?
class Game_record:
category = []
def __init__(self,name):
self.name = name
def add_category(self, cat):
self.category.append(cat)
def reset_cat(self):
self.category = []
def ret_cat(self):
return self.category
game = ["a","b"]
for each in game:
g = Game_record( each )
g.add_category("kol")
g.add_category("bol")
print(g.ret_cat())
g.reset_cat()
print(g.ret_cat())
output
['kol', 'bol']
[]
['kol', 'bol', 'kol', 'bol']
[]
To fix it declare category in __init__(), e.g.:
class Game_record:
def __init__(self,name):
self.name = name
self.category = []
...
The reason why you observe that behavior is that if you declare category right after the class, it becomes a class-level attribute rather than an object-level attribute.

Don't understand this error: name 'person' is not defined [duplicate]

This question already has an answer here:
How to use class name in class scope?
(1 answer)
Closed 3 years ago.
I'm trying to run a class named person. The error is name 'person' is not defined. How can I solve this problem?
class person:
person.count = 0
def __init__(self,gender,location,DOB):
# this is constructor method
self.__gender = gender
self.__location = location
self.__DOB = DOB
# to make the variable inaccessible from out of the class
# we have to prefix it with at least two underscores
print(person.__self)
print(person.__DOB)
person.count += 1
def getname(self):
#this is access method
return person.__self
def getDOB(self):
return person.__DOB
def _del_(self):
print('deleted')
First of all, put the line person.count = 0 inside __init__. Next, change every person to self (unless it's the class definition).

Why am I using a #classmethod instead of a normal instance method [duplicate]

This question already has answers here:
What is the purpose of class methods?
(18 answers)
Closed 4 years ago.
I watched a youtube video explaining #classmethods, instance methods, and #staticmethods. I understand how to use them. I just don't understand WHEN to use them and WHY. This is the code he gave us for the #classmethods in the youtube video.
class Employee:
# class object attributes
num_of_emps = 0
raise_amt = 1.04
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.email = first + '.' + last + '#email.com'
self.pay = pay
Employee.num_of_emps += 1
def fullname(self):
return f'{self.first} {self.last}'
def apply_raise(self):
self.pay = int(self.pay * self.raise_amt)
#classmethod
def set_raise_amt(cls, amount):
cls.raise_amt = amount
#classmethod
def from_string(cls, emp_str):
first, last, pay = emp_str.split('-')
return cls(first, last, pay)
emp_1 = Employee('Corey', 'Shaffer', 50000)
emp_2 = Employee('Test', 'Employee', 60000)
emp_3 = Employee.from_string('Ezekiel-Wootton-60000')
print(emp_3.email)
print(emp_3.pay)
Why am I using a #classmethod for the from_string method? I think it makes more sense to use the normal instance method with no decorator because we aren't referring to the class. Right?!? We are referring to each instance in which the string is being passed as an argument.
In the case of from_string, it's so it can be used as an alternative constructor. It's usage is like so
new_employee = Employee.from_string('Corey-Shaffner-50000')
Think about it, if I wanted to construct my first Employee using this method, how would I do that if it was an instance method? I don't have any instances yet to call it on.
In the case of set_raise_amt, this is so it is clear you are editing a class (aka static) variable, not an instance variable. That being said, it is generally considered poor python to use getters and setters. The user should just be able to do:
Employee.raise_amt = x

Printing Attributes of Objects in a Class in Python [duplicate]

This question already has answers here:
Printing all instances of a class
(8 answers)
Closed 9 years ago.
I've been messing around in Python for about a month and a half at this point, and I was wondering: is there a way to print the values of one class variables for all objects in that class? e.g. (I was working on a mini-game kinda thing):
class potions:
def __init__(self, name, attribute, harmstat, cost):
self.name = name
self.attribute = attribute
self.harmstat = harmstat
self.cost = cost
Lightning = potions("Lightning Potion", "Fire", 15, 40.00)
Freeze = potions("Freezing Potion", "Ice", 20, 45.00)
I'd like to be able to print a list of all the names of the potions, but I couldn't find a way to do that.
If you have a list of all the potions it's simple:
potion_names = [p.name for p in list_of_potions]
If you don't have such a list, it is not so simple; you are better off maintaining such a list by adding potions to a list, or better still, a dictionary, explicitly.
You could use a dictionary to add potions to when creating instances of potions:
all_potions = {}
class potions:
def __init__(self, name, attribute, harmstat, cost):
self.name = name
self.attribute = attribute
self.harmstat = harmstat
self.cost = cost
all_potions[self.name] = self
Now you can always find all names:
all_potion_names = all_potions.keys()
and also look up potions by name:
all_potions['Freezing Potion']
You can use the garbage collector.
import gc
print [obj.name for obj in gc.get_objects() if isinstance(obj, potions)]
You could use a class attribute to hold references to all Potion instances:
class Potion(object):
all_potions = []
def __init__(self, name, attribute, harmstat, cost):
self.name = name
self.attribute = attribute
self.harmstat = harmstat
self.cost = cost
Potion.all_potions.append(self)
Then you can always access all the instances:
for potion in Potion.all_potions:

Calling a parent class constructor from a child class in python [duplicate]

This question already has answers here:
Chain-calling parent initialisers in python [duplicate]
(3 answers)
How to invoke the super constructor in Python?
(7 answers)
Closed 6 years ago.
So if I have a class:
class Person(object):
'''A class with several methods that revolve around a person's Name and Age.'''
def __init__(self, name = 'Jane Doe', year = 2012):
'''The default constructor for the Person class.'''
self.n = name
self.y = year
And then this subclass:
class Instructor(Person):
'''A subclass of the Person class, overloads the constructor with a new parameter.'''
def __init__(self, name, year, degree):
Person.__init__(self, name, year)
I'm a bit lost on how to get the subclass to call and use the parent class constructor for name and year, while adding the new parameter degree in the subclass.
Python recommends using super().
Python 2:
super(Instructor, self).__init__(name, year)
Python 3:
super().__init__(name, year)

Categories

Resources