Functions and attributes of a person via dictionaries - python

I'm really struggling trying to understand functions and how they can be used to create attributes or properties (in this case i'm tasked with a person)
The following is my code to declare the person in a dictionary,
def format(person):
return "Name:\t" + person['name']
def display(person):
print(format(person))
person = {'name':"Bilbo Baggins"}
I then can call the display to produce;
Name = Bilbo Baggins
I then have to add to the dictionary a property storing the weight and height (say both of which are 0 for now) of my person, which i have done by;
person['height'] = 0
person['weight'] = 0
I now need to create a function (called create_person) that has the 3 parameters (name, height and weight), and modify my earlier code to use this function and alongside printing Name: Bilbo Baggins also prints the weight(in kg) and height(in m).
The overall aim of this is to find out the BMI of a person, BMI is calculated by weight/height2. I also need to add a function that takes a single person object from the previous dictionary/function as a parameter and returns the BMI of the person. Is that possible through linking the two?

class Person:
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight
# This is called when you print(PERSON OBJECT)
def __repr__(self):
return self.name + " " + self.height + " " + self.weight
def BMI(self):
return (self.weight/self.height)/self.height
This allows you to create a person like so:
person_one = Person("Bilbo", 177, 72.7)
print(person_one)
bmi = person_one.BMI()

Related

printing a string in object oriented programming

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

creating an object from user input

So I'm fairly new to python and I wanted to make a program that creates an object of a class from the user input, so I don´t have to make 10 empty profiles. I´ve tried it like this, knowing that it'll be false, but I think it demonstrates my problem.
class Profile():
def __init__(self, weight, height):
self.weight = weight
self.height = height
def create_object():
name = input("What's your name?")
new_weight = input("What's your height?")
new_height = input("What's your weight?")
name = Profile(new_weight, new_height)
return name
If i now want to create the object:
>>> create_object()
What's your name? test
What's your height? 23
What's your weight? 33
<__main__.Profile object at 0x000002564D7CFE80>
>>> test()
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
test()
NameError: name 'test' is not defined
or should I use a dictonary and if yes, how?
In my experience, it is not necessary to specifically name each instance of a class. Instead, you could do as some commenters suggested and add each new object to a dictionary, like so:
object_dict = {}
for i in range(10):
name = input("what's your name")
object_dict[name] = create_object()
The difference to note here is that I moved the name portion of your funtion to outside of the create_object() scope. To my knowledge, there are no "easy" or "clean" ways to create variables in python with a string as the user input (especially not if you are new to python).
If what you are doing doesn't necessarily need the name, and the user details are only for data storage, then it would be more concise to save the name as a property in your class, like so:
class Profile():
def __init__(self, weight, height, name):
self.weight = weight
self.height = height
self.name = name
And then when you generate the profiles, simply add them to a list:
for i in range(10):
object_list.append(create_object())
One last thing, the input method always returns a string. So if you plan to do math with the weight and height values, you will need to change the input from a string to a number, which you can do by surrounding the input() call with int() like
weight = int(input("What's your weight?"))
height = int(input("What's your height?"))

Problems with multiplying a class variable with an instance

I am new to pyhton and also new to working with classes. I am working on the below problem where I want to multiply the class variable (raise_amount) by the instance salary. However, when i do this, I get None as output. I would like to get the salary amount per person multiplied by 1.04. Any help will be greatly appreciated.
class Person:
raise_amount = 1.04
def __init__(self, name, street_name, house_nr, post_code, salary): #:post_code, salary):
self.name = name
self.street_name = street_name
self.house_nr = house_nr
self.post_code = post_code
self.salary = salary
def street_name_and_house_nr(self):
return '{} {}'.format(self.street_name, self.house_nr)
def apply_raise(self): # here is the code that seems to have problems
self.salary = int(Person.raise_amount * self.salary)
def street_name_and_house_nr_salary(self):
return self.name + ' ' + str(self.salary)
prs_1 = Person("Mary's", 'Broadway', 304, '2526 CG', 10)
prs_2 = Person("Jhon's", 'Longstreet', 304, '2829 AK',7)
prs_3 = Person("Larry's", 'Chinstreet', 58, '3046 JP', 8)
print(Person.apply_raise(prs_1))
print(Person.apply_raise(prs_2))
print(Person.apply_raise(prs_3))
This is the output i get when i run the code
None
None
None
apply_raise() doesn't return the new salary, it just updates the salary attribute. So you should get that separately to print it.
prs_1.apply_raise()
print(prs_1.salary)
Other notes:
Conventionally the first argument to methods is self. Don't make up your own name (what does lelf mean?).
You should call methods using instance.method(), not Class.method(instance). This ensures that the proper method will be used when the instance is in a subclass.

How to return the class instance in a function in Python

I had a class challenge this week and although I returned the correct age I did not return the class instance as per instructions. I've read this post but the python 2.7 syntax seems completely different.
Instructor's notes.
The class is implemented correctly, and you create its instances correctly. But when you try to find the oldest dog, you return only its age, not the actual instance (as per instructions). The instance holds the information not only on the age, but also on the name. A minor comment: you call the function "oldest_dog" from inside the formatted string - this is unconventional, you'd better execute the function on the line before that and include only the calculated variable inside the formatted string.
class Dog:
# constructor method
def __init__(self, name, age):
self.name = name
self.age = age
# three class instance declarations
maxx = Dog("Maxx", 2)
rex = Dog("Rex", 10)
tito = Dog("Tito", 5)
# return max age instance
def oldest_dog(dog_list):
return max(dog_list)
# input
dog_ages = {maxx.age, rex.age, tito.age}
# I changed this as per instructor's notes.
age = oldest_dog(dog_ages)
print(f"The oldest dog is {age} years old.")
I have changed your code to show how you can return instances:
class Dog:
# constructor method
def __init__(self, name, age):
self.name = name
self.age = age
# three class instance declarations
maxx = Dog("Maxx", 2)
rex = Dog("Rex", 10)
tito = Dog("Tito", 5)
# return the dog with the max age
def oldest_dog(dog_list):
return max(dog_list, key=lambda x: x.age) # use lambda expression to access the property age of the objects
# input
dogs = [maxx, rex, tito]
# I changed this as per instructor's notes.
dog = oldest_dog(dogs) # gets the dog instance with max age
print(f"The oldest dog is {dog.age} years old.")
Output:
The oldest dog is 10 years old.
EDIT:
If you are not allowed to use lambda, then you have to iterate through the objects. Here an implementation without lambda of the function oldest_dog(dog_list):
# return max age instance
def oldest_dog(dog_list):
max_dog = Dog('',-1)
for dog in dog_list:
if dog.age > max_dog.age:
max_dog = dog
EDIT 2:
As #HampusLarsson stated you can also define a function which returns the property age and use it to prevent using lambdas. Here a version:
def get_dog_age(dog):
return dog.age
# return max age instance
def oldest_dog(dog_list):
return max(dog_list, key= get_dog_age)

Classes with defined functions that won't call correctly

The question is noted in the title. It might be a question of details, as always, but still, any help would be appreciated.
# create a supervilan class
class supervilan:
size = ""
color = ""
powers = ""
weapons = ""
special_ability = ""
def customs(self):
print(self.name + " has a supercool and technologic advanced suit.")
def organic_gear(self, gear):
print(self.name + " use they´re" + gear + " with mastery and precision!")
I reduced the amount of methods to facilitate:
# objects
Dracula = supervilan()
Dracula.size = "2.12cm"
Dracula.color = "white"
Dracula.organic_gear("Astucy")
Chimical = supervilan()
Chimical.size = "2.30cm"
Chimical.color = "Caucasian"
Dracula.organic_gear()
Chimical.customs()
Positional arguments are values you put in the brackets of a function (eg: function(arg1,arg2)). The organic_gear function requires two positional arguments as specified when you defined the function (organic_gear(self, gear)). However in your code you call organic_gear without specifying what "self" or "gear" are, and that's why that error message appears. There may be other errors or style improvements to be corrected but I'll leave that to people better versed in classes in python.
First, you should go through the basics of OOPs concept to work with class and instances.
Since you wants to create different instances of your supervilan class with different attribute of (size, color, etc..), you must make them instance variable not class and set default values when you are initializing the instance of your class.
class supervilan:
def __init__(self, name='', size='', color='', powers='', weapons='', special_ability=''):
self.name = name
self.size = size
self.color = color
self.powers = powers
self.weapons = weapons
def customs(self):
print(self.name + " has a supercool and technologic advanced suit.")
def organic_gear(self, gear):
print(self.name + " use they´re" + gear + " with mastery and precision!")
Now you can create different instances of your class with different attribute values
Dracula = supervilan("Dracula", "2.12cm", "white")
Chimical = supervilan("Chimical", "2.30cm", "Caucasian)

Categories

Resources