printing a string in object oriented programming - python

I'm working on a MOOC on Python Programming and am having a hard time finding a solution to a problem set. I hope you can provide some assistance.
The problem statement is:
This problem uses the same Pet, Owner, and Name classes from the previous problem.
In this one, instead of printing a string that lists a single pet's owner, you will print a string that lists all of a single owner's pets.
Write a function called get_pets_string. get_pets_string should have one parameter, an instance of Owner. get_pets_string should return a list of that owner's pets according to the following format:
David Joyner's pets are: Boggle Joyner, Artemis Joyner
class Name:
def __init__(self, first, last):
self.first = first
self.last = last
class Pet:
def __init__(self, name, owner):
self.name = name
self.owner = owner
class Owner:
def __init__(self, name):
self.name = name
self.pets = []
Add your get_pets_string function here!
Here's my code:
def get_pets_string(Owner):
result = Owner.name.first + " " + Owner.name.last + "'s" + " " + "pets are:" + Pet.name
return result
My code is getting the following error:
AttributeError: type object 'Pet' has no attribute 'name'
Command exited with non-zero status 1
Below are some lines of code that will test your function. You can change the value of the variable(s) to test your function with different inputs.
If your function works correctly, this will originally
print:
David Joyner's pets are: Boggle Joyner, Artemis Joyner
Audrey Hepburn's pets are: Pippin Hepburn
owner_1 = Owner(Name("David", "Joyner"))
owner_2 = Owner(Name("Audrey", "Hepburn"))
pet_1 = Pet(Name("Boggle", "Joyner"), owner_1)
pet_2 = Pet(Name("Artemis", "Joyner"), owner_1)
pet_3 = Pet(Name("Pippin", "Hepburn"), owner_2)
owner_1.pets.append(pet_1)
owner_1.pets.append(pet_2)
owner_2.pets.append(pet_3)
print(get_pets_string(owner_1))
print(get_pets_string(owner_2))
Could you please offer some guidance on what I'm not doing right with my code?

In your code, the name is an instance variable of Pet class. So, to access name of Pet you need an instance of Pet class. But in your code in the Pet.name, the Pet refers to the class and as there is no class variable name in Pet class, the above error is displayed.
To fix this, you can use the member pets of Owner class representing list of Pet object. So in the get_pets_string() you can iterate over pets member of Owner and print names of all the pets.
So after change to get_pets_string(), it will look like -
def get_pets_string(owner):
result = owner.name.first + " " + owner.name.last + "'s pets are: " + ", ".join(p.name.first + " " + p.name.last for p in owner.pets)
return result
Here I have used join() to show the name of all the pets separated by comma

Related

Why is it when I call an attribute of my class, it is printing an older variable instead of the latest one?

I am working with Python class and methods at the moment, and I have the following code:
class Employee:
def __init__(self, first,last):
self.first = first
self.last = last
self.email = first + '.' + last + "#gmail.com"
def fullname(self):
return f'{self.first} + {self.last}'
emp_1 = Employee('John','Smith')
empl_1.first = 'Patrick'
print(emp_1.first)
print(emp_1.email)
print(emp_1.fullname())
And the output is:
Patrick
John.Smith#gmail.com
Patrick Smith
What I am struggling to understand is that when I print the first name by itself, and the full name of the employee, it is using the latest first name, which is defined to be 'Patrick'. However, for the email function, it is still using 'John'. Can someone kindly explain why this is the case?
You only define self.email once - when initialising the object. It will not magically update whenever you change other variables.

Python deleting a class object in run time

This is my code for reference:
class Manager(Employee):
def __init__(self, first, last, position, salary):
super().__init__(first, last, position)
self.salary = salary
def getinfo(self):
return self.first, self.last, self.position, self.salary
def give_raise(self, employee):
if type(employee) == type(Teller_1):
employee.hourly = int(employee.hourly * 1.10)
else:
employee.salary = int(employee.salary * 1.10)
def fire_employee(self, employee):
if type(employee.first) == type(Branch_manager) or type(employee) == type(Bank_executive):
print ("you cannot fire someone in an equal or higher position")
else:
print ("you have successfully fired " + str(employee.first) + " " + str(employee.last))
del employee
print (Analyst_1)
Analyst_1 = SalaryEmployee('Bob', 'Dun', 'Account Analyst', 40000)
When I put in this code:
Branch_manager.fire_employee(Analyst_1)
I want it to remove the object "Analyst_1". However, all it is doing is removing the reference variable "employee" and not the object itself.
How can I remove the actual object itself and not just the reference variable?
You can delete a name using the del keyword or the delattr built-in function, but you can't delete an object. (Objects don't get deleted, they get garbage collected when no names refer to them anymore.)
If your method looks like:
def fire_employee(employee):
...
and you call it like
fire_employee(Analyst_1)
then the object that the name Analyst_1 refers to will be the same object that the name employee refers to. So even if you delete one of those names, the object itself will still exist as long as the other name still references it.
You can delete the name from the global namespace, if you know what namespace it is and what name it is:
def fire_employee(employee_name):
module_object = sys.modules[__name__]
delattr(module_object, employee_name)
which you would call like this instead:
# Note that we pass a *string*, "Analyst_1", and not the *object*.
fire_employee('Analyst_1')
But if you're going to go that route, you'd be better off keeping the employee name to object mapping in its own data structure, likely a dict object as was already suggested.

Create an instance of a class and rename it based on user input

I have created a (somewhat) conversational bot and I want it to be able to create a model of the people whose names it hears. I wish to do this by having it create a new instance of my "person" class, and have that class instance named as that person (as in Bob, Alice, etc.) I've been at this all night, thought I had it because it said I had created the instance, but when trying to reference said instance of the class, it tells me that the name 'Bob' is not defined:
properNouns = [word for word,pos in taggedSent if pos == 'NNP']
if properNouns:
npn = str(properNouns)
print(npn) # ['Bob']
npn = re.sub('[\[\]\,\']', '', npn)
print(npn) # Bob
newPerson = Self(npn,'','','','','','','','','','','','','','') # Put "Bob" as the fName
newPerson.__name__ = npn # Change the instance name to "Bob" (well, try anyway)
print(str(newPerson.__name__) + " was created!") # Bob was created!
print(Bob.fName + " is the first name") # NameError: name 'Bob' is not defined
My base class is as follows:
class Self(): # A starter concept of a Host's concept of Self/Me
def __init__(self, fName, lName, DoB, job, hColor, eColor, sex, homeTown, homeState, whatIHave):
self.fName = fName
self.lName = lName
self.DoB = DoB
self.job = job
self.hColor = hColor
self.eColor = eColor
self.sex = sex
self.homeTown = homeTown
self.homeState = homeState
self.whatIHave = whatIHave
def getFullName(self):
fullName = str(self.fName) + ' ' + str(self.lName)
return fullName.title()
I can successfully manually create an instance and subsequently call up its attributes via dot notation if I hard-code it in advance, but that is not how this needs to work (If in the conversation I say I met with Bob, I need the bot to create a new instance of the Self class named Bob.)
mySelf = Self('Bob','Jones',"Coder",'19730101',black','brown','F','Boston','Massachusetts','a Jeep Wrangler')
And if I subsequently print a Bob.fName, I get Bob....
I can do some fairly decent coding but this is a relatively new area for me, and it may be that I've seen what is the answer but simply don't understand what I'm seeing well enough to know it's what I need, so apologies. I've seen many posts with very similar titles, but they do not seem to have the answer for what I am looking to do here, which seems simple to me: If I create a new "Self" (newSelf = Self), then I want to rename newSelf to "Bob".
Alternatively, and I would think easier, would be to have the new Self created with the proper name to begin with but I can't find a way to take a variable containing the name and make that name = the new Self...
Thanks for your help. I've been at this for over six hours now.

Declare objects as an attribute of another object in python

I try to create a tree of objects / not classes. I mean i do not want to create relations between the objects in prototype level, but in instance level so the relations between the objects will be solved with the code.
Here i wrote something
class human :
def __init__ (self,Name,Surname,Gender,Age,Father,Mother) :
self.Name = Name
self.Surname = Surname
self.Gender = Gender
self.Age = Age
self.Father = Father
self.Mother = Mother
class family :
def __init__ (self,Surname,Members) :
self.Surname = Surname
self.Members = Members
def ListMembers (self) :
for member in self.Members :
print (self.Surname +' family member ' +member.Name + ' '+ member.Surname + ' is ' + member.Age + " years old ")
human1 = human( 'Mary','Walter','Female','42','Jason White','Sally White')
human2 = human('Charles', 'Walter', 'Male', '45', 'Samuel Ribbon', 'Angie Ribbon')
human3 = human('Claire', 'White', 'Female', '16', 'Charles Walter', 'Mary Walter')
WalterFamily = family('Walter',(human1,human2,human3))
WalterFamily.ListMembers
When i run this code WalterFamily.ListMembers prints nothing.
What is exact way of nesting objects in another object ?
Like i tried to do here : Nesting 3 humans inside a family and also reach to the attributes of these objects..
The last line of code is not what you want. All functions that belong to a class (like your ListMembers function) is a function stored in a variable name.
When you have what you currently have:
WalterFamily.ListMembers
You only print the function object stored at the ListMembers variable. To actually call it, you need to add parenthesis.
WalterFamily.ListMembers()
In Python everything is an object, including functions. So WalterFamily.ListMembers is just a reference to the object. To call the function you need WalterFamily.ListMembers()

Searching a list to see if there is a match python

Basically this is within a class which appends objects of another class to list self. There are 200 objects in list self. So basically if I call self[1] I will get ['John',['Alex', 'Rob']. Basically 'john' refers to self.firstname and the other names refer to there group members. For example the below will print the firstnames and groupmembers of each object for all 200 objects
for line in self:
print line.firstname
for line in self:
print line.groupmembers
Now I have to create something that goes through all the names and checks the names. So basically if John has Alex and Rob as members then there has to be another object with a first name Alex and another object with a firstname Rob. So say there is no object with firstname Alex I want to print 'mismatch'. This is what I have so far but its not doing what its intended to do.
def name(self):
firstnames = []
for item in self:
firstnames.append(item.firstname)
for item1 in self:
for i in item1.groupmembers:
if i not in hello:
print 'mismatch'
Okay so first off, line and self are bad variable names.
self should only be used within a class to be used as a way to call or use its own variables.
Secondly, you say each value in this self list contains values like ['John',['Alex', 'Rob'], but then you go on to use it like a class object... and frankly that don't do make none sense.
So to remedy this, I'm going to assume its done with class objects. I would also rename self to something like school, and instead of calling an element of self; line, which yields no information to the reader.. call it a student!
I'm going to assume your class would start looking like this:
class Student:
# having an empty default value makes it easy to see what types variables should be!
firstname = ""
groupmembers = []
def __init__(self,firstname,groupmembers ):
self.firstname = firstname
self.groupmembers = groupmembers
Then if you have a list of people you can loop through them like so..
>>>school = [Student("foo", ["bar", "that guy"]),
Student("bar", ["foo", "that guy"])]
>>>for student in school:
print student.firstname
print student.groupmembers
foo
["bar", "that guy"]
bar
["foo", "that guy"]
Then to check it a students group members are in school you can add a function to the Student class
class Student:
# having an empty default value makes it easy to see what types variables should be!
firstname = ""
groupmembers = []
def __init__(self,firstname,groupmembers ):
self.firstname = firstname
self.groupmembers = groupmembers
def group_present(self, school):
# This is how you would get all the names of kids in school without list comprehension
attendance = []
for student in school:
attendance.append(student.firstname)
# this is with list comprehension
attendance = [ student.firstname for student in school]
#compare group members with attendance
#note that I write student_name, not student
## helps point out that it is a string not a class
for student_name in self.groupmembers:
if not student_name in attendance:
print "Group member '{}' is missing :o!! GASP!".format(student_name)
In idle:
>>> school[0].group_present(school)
Group member 'that guy' is missing :o!! GASP!
Hope that helps!
I am not sure if i understand exactly but maybe you can use contains
self[1].__contains__('Alex')
this should return true in case of existence or false otherwise.

Categories

Resources