I'm trying to figure out how to print out the instance of a class with user defined attributes in Python 3.
Here is the code I have:
class Attendie:
def __init__(self, fname, lname, company, state, email):
self.fname = fname
self.lname = lname
self.company = company
self.state = state
self.email = email
def getFname(self):
return self.fname
def getLname(self):
return self.lname
def getCompany(self):
return self.company
def getState(self):
return self.state
def getEmail(self):
return self.email
def main():
fname = input("what is the attendie's first name? ")
lname = input("What is the attendie's last name? ")
company = input("What company is the attendie with? ")
state = input("What state is the attendie from? ")
email = input("What is the attendie's email address? ")
Person = Attendie(fname, lname, company, state, email)
print(Person.getFname)
print(Person.getLname)
print(Person.getCompany)
print(Person.getState)
print(Person.getEmail)
if __name__ == '__main__': main()
After I run the program I get these types of error messages.
bound method Attendie.getFname of <main.Attendie object at 0x00000000031DCDD8
It seems that you are not calling the methods.
In [1]: class A(object):
...: def __init__(self, n):
...: self.n = n
...: def get_n(self):
...: return self.n
...:
In [2]: a = A(5)
In [3]: a.get_n
Out[3]: <bound method A.get_n of <__main__.A object at 0xa56516c>>
In [4]: a.get_n()
Out[4]: 5
Changing your code as follows should fix it:
print(Person.getFname())
print(Person.getLname())
print(Person.getCompany())
print(Person.getState())
print(Person.getEmail())
Related
I've created a class named Patient that has attributes for patient information. I'm supposed to use an accessor and mutator method for each attribute. Then I've created another file to access the class and insert patient information to print. Every time I print I don't get what I expect but I get <Assignment4Q1PatientClass2nd.Patient object at 0x000002429E038A00>.
Here's what is on my first file (File name is Assignment4Q1PatientClass2nd):
class Patient:
def __init__(self, fname, mname, lname, address, city, state, zipcode, phone, ename, ephone):
self._fname = fname #first name
self._mname = mname #middle name
self._lname = lname #last name
self._address = address #address
self._city = city #city for address
self._state = state #state for address
self._zipcode = zipcode #zipcode for address
self._phone = phone #phone number
self._ename = ename #emergency name
self._ephone = ephone #emergency phone
#add patient information
def addFirstName(self, firstname):
self._fname = self._fname + firstname
def addMiddleName(self, middlename):
self._mname = self._mname + middlename
def addLastName(self, lastname):
self._lname = self._lname + lastname
def addAddress(self, locaddress):
self._address = self._address + locaddress
def addCity(self, cityname):
self._city = self._city + cityname
def addState(self, statename):
self._state = self._state + statename
def addZipcode(self, zipcodenum):
self._zipcode = self._zipcode + zipcodenum
def addPhone(self, phonenum):
self._phone = self._phone + phonenum
def addEName(self, emergencyname):
self._ename = self._ename + emergencyname
def addEPhone(self, emergencyphone):
self._ephone = self._ephone + emergencyphone
#get/return all information of the Patient
def getPatientFirstName(self):
return "First Name:" + self._fname
def getPatientMiddleName(self):
return "Middle Name:" + self._mname
def getPatientLastName(self):
return "Last Name:" + self._lname
def getPatientAddress(self):
return "Address:" + self._address
def getPatientCity(self):
return "City:" + self._city
def getPatientState(self):
return "State:" + self._state
def getPatientZipcode(self):
return "ZIP:" + self._zipcode
def getPatientPhone(self):
return "Phone:" + self._phone
def getPatientEName(self, emergencyname):
return "Emergency Contact:" + self._ename
def getPatientEPhone(self, emergencyphone):
return "Emergency Phone:" + self._ephone
on the second file is:
from Assignment4Q1PatientClass2nd import Patient
pat = Patient("James", "Edward", "Jones", "345 Main Street", "Billings", "Montanna", 59000, "406-555-1212", "Jenny Jones", "406-555-1213")
print(pat)
What did you expect from your print statement?
The class actually don't "know" what to print. You must provide a way to represent that class as a string, so we can print that string.
In practice, we do this by adding a function called "__repr__", the representation of this class. Python automatically identifies this as a especial one, just like "__init__".
Here is a small example to you:
class Patient:
def __init__(self, name):
self._name = name
def getPatientName(self):
return self._name
def __repr__(self):
return "Hey! My name is " + self.getPatientName()
pat = Patient("Dikson")
print(pat)
# Hey! My name is Dikson
Hope it's clear :)
I found this fantasy name generator here.
I am trying to adapt the code to suit my purpose. I want to create an NPC name automatically, using the function name_gen within the class NPC. With the NPC characteristics being:
class NPC:
def __init__(self, name, age, gender):
self.name = name_gen
self.age = 25
self.gender = M
The code from the name generator I need is the following:
from random import randrange
def line_appender(file_path, target):
file = open(file_path, "r")
splitfile = file.read().splitlines()
for line in splitfile:
target.append(line)
def name_selector(target_list):
selected = target_list[randrange(len(target_list))]
return selected
def name_builder(first_name_list_path, last_name_list_path):
first_name_list = []
last_name_list = []
line_appender(first_name_list_path, first_name_list)
line_appender(last_name_list_path, last_name_list)
first_name_selected = name_selector(first_name_list)
last_name_selected = name_selector(last_name_list)
name = first_name_selected+" "+last_name_selected
return name
Now the only thing I think I still need to do, is to generate the name from within the class NPC. I thought doing something like:
def name_gen
if gender == "M":
name = name_builder("first_name_male.txt", "last_name.txt")
elif gender == "F":
name = name_builder("first_name_female.txt", "last_name.txt")
But I don't understand how to make the name_gen function check the class NPC properties,
so that it generates the desired name.
Could someone perhaps help me out?
EDIT
Thank you for all the solutions! I am pretty new to Python; In order to test Samwises solution, I tried to run it as a separate script (in order to check whether I would get a name) with the code below. It does however not print anything. I'm putting this in an EDIT because I think it might be a trivial question. If it is worth posting a separate question, please let me know:
import random
running = True
npc_input_messsage = "npc = NPC(25, 'M')"
class NameChooser:
def __init__(self, file_path):
with open(file_path) as f:
self._names = f.read().splitlines()
def choice(self):
return random.choice(self._names)
first_choosers = {
"M": NameChooser("first_name_male.txt"),
"F": NameChooser("first_name_female.txt"),
}
last_chooser = NameChooser("last_name.txt")
def name_gen(gender):
return f"{first_choosers[gender].choice()} {last_chooser.choice()}"
class NPC:
def __init__(self, age, gender):
self.name = name_gen(gender)
self.age = age
self.gender = gender
while running:
npc = input(npc_input_messsage)
# I'm entering npc = NPC(25, "M")
print(npc)
Your name generator is a little over-complicated IMO. I'd suggest wrapping all the file reading and name selection stuff in a simple class so you can define it once and then instantiate it for each of your name lists. Putting the file reading part in __init__ means you only do it once per list instead of re-reading the file each time you need to pick a name.
import random
class NameChooser:
def __init__(self, file_path):
with open(file_path) as f:
self._names = f.read().splitlines()
def choice(self):
return random.choice(self._names)
Now you can define three NameChoosers and a name_gen function that picks among them:
first_choosers = {
"M": NameChooser("first_name_male.txt"),
"F": NameChooser("first_name_female.txt"),
}
last_chooser = NameChooser("last_name.txt")
def name_gen(gender):
return f"{first_choosers[gender].choice()} {last_chooser.choice()}"
And now you can define an NPC class that takes age and gender as arguments to the constructor, and picks a random name using name_gen():
class NPC:
def __init__(self, age, gender):
self.name = name_gen(gender)
self.age = age
self.gender = gender
def __str__(self):
return f"{self.name} ({self.age}/{self.gender})"
npc = NPC(25, "M")
print(npc) # prints "Bob Small (25/M)"
I think you're confused about OOP concepts.
First, let's edit your class:
class NPC:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
See, I have assigned parameter values to the attributes.
Now let's make changes to your function:
def name_gen(gender):
if gender == "M":
name = name_builder("first_name_male.txt", "last_name.txt")
elif gender == "F":
name = name_builder("first_name_female.txt", "last_name.txt")
return name
Here I have added a parameter to your function since you're using its value.
Now let's create an instance for your class.
npc = NPC("Vishwas", 25, "M") # Instance of the class
print(name_gen(npc.gender)) # Print generated name
A straightforward way to make happen automatically would be to simply call the name generator from with the NPC.__init__() method. In the code below it's been made a private method of the class by starting its name with an underscore character. Note that the call to it has to wait until all the instance attributes it references have been assigned value.
from random import randrange
class NPC:
def __init__(self, age, gender):
self.age = age
self.gender = gender
self.name = self._name_gen()
def _name_gen(self):
if self.gender == "M":
name = name_builder("first_name_male.txt", "last_name.txt")
elif self.gender == "F":
name = name_builder("first_name_female.txt", "last_name.txt")
return name
def line_appender(file_path, target):
file = open(file_path, "r")
splitfile = file.read().splitlines()
for line in splitfile:
target.append(line)
def name_selector(target_list):
selected = target_list[randrange(len(target_list))]
return selected
def name_builder(first_name_list_path, last_name_list_path):
first_name_list = []
last_name_list = []
line_appender(first_name_list_path, first_name_list)
line_appender(last_name_list_path, last_name_list)
first_name_selected = name_selector(first_name_list)
last_name_selected = name_selector(last_name_list)
name = first_name_selected+" "+last_name_selected
return name
if __name__ == '__main__':
npc1 = NPC(25, 'M')
print(f'{npc1.name!r}')
npc2 = NPC(21, 'F')
print(f'{npc2.name!r}')
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
I started learning python. Here is a simple program:
class StudentRepo:
def __init__(self):
self.student_list = []
def add(self, student):
self.student_list.append(student)
def get_list(self):
self.student_list
class Student:
def __init__(self, name, age):
self.age = age
self.name = name
from models.student.Student import Student
from services.student.StudentRepo import StudentRepo
s1 = Student("A", 10)
s2 = Student("B", 11)
# What is the issue here ?
StudentRepo.add(s1)
StudentRepo.add(s2)
studentList = StudentRepo.get_list()
for student in studentList:
print(student.name)
What is the issue with s1 = Student("A", 10) ?
There are two mistakes in your code. First, this:
def get_list(self):
self.student_list
should be:
def get_list(self):
return self.student_list
Second, you're using the class StudentRepo where you should be using an instance of StudentRepo:
s1 = Student("A", 10)
s2 = Student("B", 11)
my_roster = StudentRepo()
my_roster.add(s1)
my_roster.add(s2)
studentList = my_roster.get_list()
for student in studentList:
print(student.name)
I need some help understanding python scoping with classes.
For instance this is a perfectly valid program, which makes sense to me
import json
class Person(object):
def __init__(self, firstname, lastname, age,address):
self.firstname = firstname
self.age = age
self.lastname = lastname
self.address = address
class Address(object):
def __init__(self,zipcode,state):
self.zipcode = zipcode
self.state = state
personlist = []
for count in range(5):
address = Address("41111","statename")
person = Person("test","test",21,address)
print(count)
personlist.append(person)
jsonlist = []
for Person in personlist:
print Person.firstname
d = {}
d['firstname'] = Person.firstname
d['lastname'] = Person.lastname
d['age'] = Person.age
d['zipcode'] = Person.address.zipcode
d['state'] = Person.address.state
jsonlist.append(d)
jsondict = {}
jsondict["People"] = jsonlist
jsondict["success"] = 1
json_data = json.dumps(jsondict, indent =4)
print json_data
But this next program gives me an error
import json
class Person(object):
def __init__(self, firstname, lastname, age,address):
self.firstname = firstname
self.age = age
self.lastname = lastname
self.address = address
class Address(object):
def __init__(self,zipcode,state):
self.zipcode = zipcode
self.state = state
def main():
personlist = []
for count in range(5):
address = Address("41111","statename")
person = Person("test","test",21,address)
print(count)
personlist.append(person)
jsonlist = []
for Person in personlist:
print Person.firstname
d = {}
d['firstname'] = Person.firstname
d['lastname'] = Person.lastname
d['age'] = Person.age
d['zipcode'] = Person.address.zipcode
d['state'] = Person.address.state
jsonlist.append(d)
jsondict = {}
jsondict["People"] = jsonlist
jsondict["success"] = 1
json_data = json.dumps(jsondict, indent =4)
print json_data
main()
My question is why creating the classes in white space valid but creating them inside a function not valid. Is there any way to create them in the main function and it be valid?
EDIT:
Error is
File "jsontest.py", line 9, in main
person = Person("test","test",21,address)
UnboundLocalError: local variable 'Person' referenced before assignment
The problem is that you use a variable with the same name as your class Person (also called "shadowing"):
for Person in personlist:
Python detects that you use it as a local variable and raises an error:
UnboundLocalError: local variable 'Person' referenced before
assignment
which means that you try to use a local variable before it was assigned in the following line:
person = Person("test","test",21,address)
You can find more information about it here