I have a class User and a subclass Admin that I am trying to work on, but when I try to call an instance of them I keep getting None returned after the result
class User:
def __init__(self, first_name, last_name, age, height):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.height = height
def describe_user(self):
print(f"{self.first_name} {self.last_name}\n{self.age} " \
f"years old\n{self.height} cm tall")
def greet_user(self):
print(f"Hi, {self.first_name} {self.last_name}! ")
class Admin(User):
def __init__(self, first_name, last_name, age, height):
super().__init__(first_name, last_name, age, height)
self.privileges = ['post', 'delete post', 'ban user']
def show_privileges(self):
print(f"{self.first_name} can:")
for item in self.privileges:
print(item)
person = Admin('John', 'Doe', 20, 180)
print(person.describe_user())
print(person.show_privileges())
John Doe
20 years old
180 cm tall
None
John can:
post
delete post
ban user
None
I am trying to find out why this happens and how to fix it
person.describe_user() returns None implicitly since it doesn't have a return statement within the function body(it only prints a value). This causes print(person.describe_user()) to print None.
The solution is to just write person.describe_user() without the extra print(), and similarly for the following line.
describe_user and show_privileges do their own printing; they don't have a return value, so they implicitly return None. Get rid of the print around the call to each of them, making the end of your code just:
person = Admin('John', 'Doe', 20, 180)
person.describe_user()
person.show_privileges()
and you won't print their useless return values (None).
Related
I have a class (Student) with different attributes, such as studentId, address, and courses. My str method for the class returns all the information that the user put in. However, for the attributes that are lists, such as courses, the location of the information is printed out instead of the actual information. Here is the code (sorry it's a little long, there's a bunch of classes):
class Person:
__name = None
__age = None
__address = None
def __init__(self, name, age=0, address=None):
self.set_name(name)
self.set_age(age)
self.set_address(address)
def __str__(self):
return 'Name: ' + self.__name + '\n' + \
'Age: ' + str(self.__age) + '\n' + \
'Address: ' + str(self.__address)
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_age(self, age):
self.__age = age
def get_age(self):
return self.__age
def set_address(self, address):
self.__address = address
def get_address(self):
return self.__address
class Student(Person):
def __init__(self, name, studentID= None, age= 0, address= None):
super(Student, self).__init__(name, age, address)
self.set_studentID(studentID)
self.__courses =[]
def __str__(self):
result = Person.__str__(self)
result += '\nStudent ID:' + self.get_studentID()
for item in self.__courses:
result += '\n ' + str(item)
return result
def set_studentID(self, studentID):
if isinstance(studentID, str) and len(studentID.strip()) > 0:
self.__studentID = studentID.strip()
else:
self.__studentID = 'NA'
def get_studentID(self):
return self.__studentID
def add_course(self, course):
print('in add_course')
self.__courses.append(course)
def get_courses(self):
for i in range(len(self.__courses)):
return self.__courses[i]
class Course:
__courseName = None
__dept = None
__credits = None
def __init__(self, courseName, dept= 'GE', credits= None):
self.set_courseName(courseName)
self.set_dept(dept)
self.set_credits(credits)
def __str__(self):
return self.get_courseName() + '/' + self.get_dept() + '/' + str(self.get_credits())
def set_courseName(self, courseName):
if isinstance(courseName, str) and len(courseName.strip()) > 0:
self.__courseName = courseName.strip()
else:
print('ERROR: Name must be a non-empty string')
raise TypeError('Name must be a non-empty string')
def get_courseName(self):
return self.__courseName
def set_dept(self, dept):
if isinstance(dept, str) and len(dept.strip()) > 0:
self.__dept = dept.strip()
else:
self.__dept = "GE"
def get_dept(self):
return self.__dept
def set_credits(self, credits):
if isinstance(credits, int) and credits > 0:
self.__credits = credits
else:
self.__credits = 3
def get_credits(self):
return self.__credits
students = []
def recordStudentEntry():
name = input('What is your name? ')
age = input('How old are you? ')
studentID= input('What is your student ID? ')
address = input('What is your address? ')
s1 = Student(name, studentID, int(age), address)
students.append(s1)
s1.add_course(recordCourseEntry())
print('\ndisplaying students...')
displayStudents()
print()
def recordCourseEntry():
courses = []
for i in range(2):
courseName = input('What is the name of one course you are taking? ')
dept = input('What department is your course in? ')
credits = input('How many credits is this course? ')
c1 = Course(courseName, dept, credits)
print(c1)
courses.append(c1)
displayCourses(courses)
return courses
def displayCourses(courses):
print('\ndisplaying courses of student... ')
for c in range(len(courses)):
print(courses[c])
def displayStudents():
for s in range(len(students)):
print()
print(students[s])
recordStudentEntry()
This is how the code above prints out the 'displaying students...' part:
displaying students...
Name: sam
Age: 33
Address: 123 st
Student ID:123abc
[<__main__.Course object at 0x000002BE36E0F7F0>, <__main__.Course object at
0x000002BE36E0F040>]
I know that it is printing out the location because I need to index into the list. However, the length of the list will be different every time. Normally if I wanted to index into a list, for example, to print a list of names, I would do:
listOfNames = ['sam', 'john', 'sara']
for i in range(len(listOfNames)):
print(listOfNames[i])
or
listOfNames = ['sam', 'john', 'sara']
for i in listOfNames:
print(i)
(not sure what if any difference there is between the 2 ways since they both print out the same way:)
sam
john
sara
How can I write something like the indexing into a list technique shown here in my str method for my class so that it prints the information and not the location?
It would be good to keep to the standard conventions for Python, such as naming
private attributes for objects with single underscores, not double underscores.
The latter are reserved for Python "internal" attributes and methods.
Also, it is convention to use object attributes for objects with get/set methods,
not class attributes. This will make it easier to inspect your objects, while
still maintaining data hiding. Example:
class Course:
def __init__(self, courseName, dept= 'GE', credits= None):
self._courseName = None
self._dept = None
self._credits = None
self.set_courseName(courseName)
...
Your question about why the courses don't print out the way you expected
is rooted in a programming error with the way you programmed the recording
of courses. In recordCourseEntry(), you record two courses and put them
in a list. However, you pass that to your Student object using a method
intended for one course at a time. My suggested fix would be:
...
# s1.add_course(recordCourseEntry())
courses = recordCourseEntry()
for course in courses:
s1.add_course(course)
...
This will probably be enough to get you going. An example output I got was:
Name: Virtual Scooter
Age: 33
Address: 101 University St.
Student ID:2021
ff/GE/3
gg/GE/3
This question already has answers here:
python class attribute
(3 answers)
List as class attribute
(2 answers)
Closed 1 year ago.
I am new to Python programming and I was coding the following script to increase my understanding of Pyhton OOP.
# Python OOP
class Employee:
num_of_emps = 0
raise_amt = 1.04
def __init__(self, first_name, last_name, pay):
self.first_name = first_name
self.last_name = last_name
self.pay = pay
self.email = first_name.lower() + '.' + last_name.lower() + '#company.com'
Employee.num_of_emps += 1
def fullname(self):
return self.first + ' ' + self.last
def apply_raise(self):
self.pay = int(self.pay * self.raise_amt)
#classmethod
def from_string(cls, emp_str):
name, surname, pay = emp_str.split('-')
return cls(name, surname, pay)
class Developer(Employee):
raise_amt = 1.01 # overriding raise_amt
def __init__(self, first_name, last_name, pay, prog_lang=None):
super().__init__(first_name, last_name, pay)
self.prog_lang = prog_lang
#classmethod
def with_prog_lang(cls, first_name, last_name, pay, prog_lang):
return cls(first_name, last_name, pay, prog_lang)
#classmethod
def from_string_kebab_case(cls, emp_str):
first_name, last_name, pay, prog_lang = emp_str.split('-')
return cls(first_name, last_name, pay, prog_lang)
class Manager(Employee):
raise_amt = 1.1
supervised_employee = []
def __init__(self, first_name, last_name, pay, employees=None):
super().__init__(first_name, last_name, pay)
if employees is not None:
self.supervised_employee.append(employees)
def add_emp(self, employee):
if employee not in self.supervised_employee:
self.supervised_employee.append(employee)
def remove_emp(self, employee):
if employee in self.supervised_employee:
self.supervised_employee.pop()
def show_employees(self):
if (len(self.supervised_employee) == 0):
print(f"{self.first_name} is managing no one")
else:
print(f"{self.first_name} is managing ", end='')
output = ''
for emp in self.supervised_employee:
output = output + emp + ' ,'
print(f"{output}")
emp1 = Developer('Burak', 'Aksoy', 5000)
manager1 = Manager('Ahmet', 'Nazli', 10000, 'Burak')
manager1.add_emp('John')
manager2 = Manager('Faruk', 'Tuncer', 10000)
print(manager1.supervised_employee)
manager1.show_employees()
manager2.show_employees()
Here, I have the following output as I run the code ->
{'first_name': 'Ahmet', 'last_name': 'Nazli', 'pay': 10000, 'email': 'ahmet.nazli#company.com'}
['Burak', 'Harun']
Ahmet is managing Burak ,John ,
Faruk is managing Burak ,John ,
When I add 'Burak' and 'John' as employees to manager1, I see that manager2 is also affected by this, but I don't want this to happen.. How do you think I can fix this?
Any help is appreciated.
Best.
When printing out the str() function for the Manager() class the employees list prints out the location of the objects in memory instead of in type(str) format. The rest of the Manager str prints out fine, but I can't figure out how to get the employees list to print out. I'm just using the GUI to test aspects of the code for now.
Thank you in advance for your time.
Image of incorrect output on GUI
import random
from random import randint
from tkinter import *
import tkinter as tk
from tkinter import ttk
class Employees(object):
'''
'''
num_emps = 0
def __init__(self, first_name, last_name, pay, emp_id):
self.first_name = first_name
self.last_name = last_name
self.pay = pay
self.emp_id = self.IdMaker()
Employees.num_emps += 1
def get_first_name(self): #Retrieves First Name
return self.first_name
def get_last_name(self): #Retrieves Last Name
return self.last_name
def get_full_name(self): #Retrieves Full Name
return '{} {}'.format(self.first_name, self.last_name)
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name}'.format(self=self)
#####---ID CLASS---#####
class IdMaker():
'''
'''
def __init__(self):
self.emp_id = 'emp_' + ''.join(str(random.randint(0, 9)) for x in range(12))
self.food_id = 'food_' + ''.join(str(random.randint(0, 9)) for x in range(12))
self.sanitation_id = 'sani_' + ''.join(str(random.randint(0, 9)) for x in range(12))
self.dinnerWare_id = 'dWare_' + ''.join(str(random.randint(0, 9)) for x in range(12))
def __str__(self):
if isinstance(self.emp_id, object):
return '{self.emp_id}'.format(self=self)
elif isinstance(self.food_id, object):
return 'food_{self.food_id}'.format(self=self)
elif isinstance(self.sanitation_id, object):
return 'sani_{self.sanitation_id}'.format(self=self)
elif isinstance(self.dinnerWare_id, object):
return 'sani_{self.dinnerWare_id}'.format(self=self)
else:
print('No such object')
#-----------------------------------------------------------------------------
class Manager(Employees):
def __init__(self, first_name, last_name, pay, emp_id, employees=None):
super().__init__(first_name, last_name, pay, emp_id)
# if schedule is None: #Schedule
# self.schedule = {}
# else:
# self.schedule = schedule
if employees is None: #Employees working for Manager
self.employees = []
else:
self.employees = employees
def add_emp(self, emp):
if emp not in self.employees:
self.employees.append(emp)
def remove_emp(self, emp):
if emp in self.employees:
self.employees.remove(emp)
def print_emps(self):
for emp in self.employees:
print(emp.get_full_name())
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name} |Pay - ${self.pay} - {self.employees}'.format(self=self)
class FOH(Manager):
def __init__(self, first_name, last_name, pay, emp_id):
Employees.__init__(self, first_name, last_name, pay, emp_id)
self.pay = pay
# if schedule is None: #Schedule
# self.schedule = {}
# else:
# self.schedule = schedule
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name} |Pay - ${self.pay}'.format(self=self)
class BOH(Manager):
def __init__(self, first_name, last_name, pay, emp_id):
Employees.__init__(self, first_name, last_name, pay, emp_id)
self.pay = pay
# if schedule is None: #Schedule
# self.schedule = {}
# else:
# self.schedule = schedule
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name} |Pay - ${self.pay}'.format(self=self)
foh_1 = FOH('Rebecca', 'Peters', 60000, None)
foh_2 = FOH('Becca', 'Peters', 60000, None)
boh_3 = BOH('Beckles', 'Peters', 60000, None)
mgr_1 = Manager('Sean', 'Sheaffer', 90000, None, [foh_1, foh_2, boh_3])
# mgr_1.add_emp([foh_2])
# mgr_1.add_emp([boh_3])
mgr_2 = Manager('Becky', 'Peters', 100000, None, [boh_3])
mgr_2.print_emps()
mgr_1.print_emps()
#####---GUI CLASS---#####
root = Tk()
root.title('DigiSous')
root.geometry("600x200")
# Creates tab control
tabControl = ttk.Notebook(root)
class GUI(Manager):
def __init__(self, master, first_name, last_name, pay, emp_id):
super().__init__(first_name, last_name, pay, emp_id)
my_frame = Frame(master)
my_frame.pack()
#Find Employees working for Manager
self.find_mgr_emps = Button(master, text="Employees", command=self.manager_emps)
self.find_mgr_emps.pack(pady=20)
self.find_mgr_emps_Entry = Entry(master, width=90, borderwidth=5)
self.find_mgr_emps_Entry.pack(pady=10)
def manager_emps(self):
self.find_mgr_emps_Entry.delete(0, END)
mgr_emps = mgr_1
self.find_mgr_emps_Entry.insert(0, mgr_emps)
#-----------------------------------------------------------------------------
e = GUI(root, None, None, None, None)
root.mainloop()
Whenever you print a list, you will see the __repr__ of those objects instead of __str__, so one way could be to override the __repr__ method to get your desired output, as for example:
def __repr__(self):
return str(self)
Another way could be to use a list comprehension when you format your string as follows:
class Manager(Employees):
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name} |Pay - ${self.pay} - {[str(x) for x in self.employees]}'.format(self=self)
I am learning about Class Inheritance and overriding methods in python. To implement my learning, I wrote this code to let me better understand how Inheritance and Overriding works. But as I ran the code, I faced this error
"RecursionError: maximum recursion depth exceeded while calling a Python object"
I have tried to increase the recursion limit to 10000, but doing so, Python interpreter stopped working in my local machine. Can anyone help me with how I can overcome the error to have my expected output?
As I am new to the community, I may lack the appropriate presentation of the problem. Feel free to ask for more detailed information about the problem.
# Increasing Recursion Limit
import sys
sys.setrecursionlimit(10000)
import random
# Parent Class
class Unique_id_creator():
def __init__(self, birthdate, birthmonth, birthyear):
self.date = birthdate
self.month = birthmonth
self.year = birthyear
def random_digits(self):
last_two_digits = random.randrange(10, 99)
return self.random_digits()
def unique_id(self):
id = int(self.date + self.month + self.year + self.random_digits())
return self.unique_id()
# Child Class
class Unique_id_distributer(Unique_id_creator):
def __init__(self, name, birthdate, birthmonth, birthyear):
Unique_id_creator.__init__(self, birthdate, birthmonth, birthyear)
self.name = name
def unique_id(self):
Unique_id_creator.unique_id(self)
return "Dear "+ str(self.name) + ", Your Unique Id is: "+ str(self.unique_id())
citizen1 = Unique_id_distributer("hasan", "01", "11", "2000")
print(citizen1.unique_id())
# Output Window
RecursionError: maximum recursion depth exceeded while calling a Python object
This line return self.random_digits() and this line return self.unique_id() are infinite recursive loops.
I assume what you intended to return was last_two_digits and id.
When you return a function call, that function has to execute to return the result of its call. Since you are calling the function you are executing it continues calling itself forever.
Corrected code
# Increasing Recursion Limit
import sys
sys.setrecursionlimit(10000)
import random
# Parent Class
class Unique_id_creator:
def __init__(self, birthdate, birthmonth, birthyear):
self.date = birthdate
self.month = birthmonth
self.year = birthyear
def random_digits(self):
last_two_digits = random.randrange(10, 99)
# convert to a string since you are concatenating the result
return str(last_two_digits)
def unique_id(self):
id = int(self.date + self.month + self.year + self.random_digits())
return id
# Child Class
class Unique_id_distributer(Unique_id_creator):
def __init__(self, name, birthdate, birthmonth, birthyear):
Unique_id_creator.__init__(self, birthdate, birthmonth, birthyear)
self.name = name
def unique_id(self):
id = Unique_id_creator.unique_id(self)
return "Dear "+ str(self.name) + ", Your Unique Id is: "+ str(id)
citizen1 = Unique_id_distributer("hasan", "01", "11", "2000")
print(citizen1.unique_id())
Additionally, you can eliminate the full call of your parent class by using super().
Child class example
# Child Class
class Unique_id_distributer(Unique_id_creator):
def __init__(self, name, birthdate, birthmonth, birthyear):
super().__init__(birthdate, birthmonth, birthyear)
self.name = name
def unique_id(self):
id = super().unique_id()
return "Dear "+ str(self.name) + ", Your Unique Id is: "+ str(id)
My homework question asks me to write the following functions using a predetermined class 'Person', it runs 5 tests, one code analyser that ensures it was done the way they want and 4 practical examples, my code passes the practical examples but the analyser fails me.
This is the question:
Using the Person class, write a function print_friend_info(person) which accepts a single argument, of type Person, and:
prints out their name
prints out their age
if the person has any friends, prints 'Friends with {name}'
class Person(object):
def __init__(self, name, age, gender):
self._name = name
self._age = age
self._gender = gender
self._friend = None
def __eq__(self, person):
return str(self) == str(person)
def __str__(self):
if self._gender == 'M':
title = 'Mr'
elif self._gender == 'F':
title = 'Miss'
else:
title = 'Ms'
return title + ' ' + self._name + ' ' + str(self._age)
def __repr__(self):
return 'Person: ' + str(self)
def get_name(self):
"""
(str) Return the name
"""
return self._name
def get_age(self):
"""
(int) Return the age
"""
return self._age
def get_gender(self):
"""
(str) Return the gender
"""
return self._gender
def set_friend(self, friend):
self._friend = friend
def get_friend(self):
"""
(Person) Return the friend
"""
return self._friend
def print_friend_info(person):
print(person._name)
print(person._age)
if person.get_friend() != None:
print("Friends with {}".format(person._friend._name))
All tests pass, including the print_friend_info tests, except for this test that outputs the following error:
----- Analysis Errors -----
You need to print the person's name in print_friend_info
You need to print the person's age in print_friend_info
You need to print the name of the person's friend in print_friend_info
I have tried your code and it works for me with Python3.6.6. I have some suggestions which could be problem. First of all your shouldn't use the protected attributes of your class (underscored variables). You have getter methods to get the data of object so use them. It seems to me that the output can fulfill the test what you mentioned in your question.
Changed part of code:
def print_friend_info(person):
print("Name: {}".format(person.get_name()))
print("Age: {}".format(person.get_age()))
if person.get_friend(): # You don't need to use "!= None". A simple if is enough.
print("Friends with {}".format(person.get_friend().get_name())
print("\n")
joe = Person("Joe", 42, "Male")
print_friend_info(joe)
mary = Person("Mary", 55, "Female")
print_friend_info(mary)
joe.set_friend(mary)
print_friend_info(joe)
Output:
>>> python3 test.py
Name: Joe
Age: 42
Name: Mary
Age: 55
Name: Joe
Age: 42
Friends with Mary