pythonic way to print variables in class Person - python

class Person:
def __init__(self, name, surname, age):
self.name = name
self.surname = surname
self.age = age
def show(self):
print(("Name: {}\nSurname: {}\nAge: {}").format(self.name, self.surname, self.age))
Is there more pythonic way to show these variables by function show?
I don't want spaghetti code when i have 34 variables in class

In the case you don't want to override __str__ and badly need show to print, not return data, it's still more pythonic to use format. I'd make few adjustment for your code:
def show(self):
person_info = "Name {name}\nSurname {surname}\nAge {age}".format(name=self.name, surname=self.surname, age=self.age)
print (person_info)
In general it's the same you had, just a bit more explicit.

Not sure if it is more Pythonic or not, but instead of defining show you can override __repr__ (you will need to return that string instead of printing it). Then instead of calling person_obj.show you can simply do print(person_obj).
class Person:
def __init__(self, name, surname, age):
self.name = name
self.surname = surname
self.age = age
def __repr__(self):
return "Name: {}\nSurname: {}\nAge: {}").format(self.name, self.surname, self.age)
print(Person('a','b', 'c'))
>> Name: a
Surname: b
Age: c
This will display correctly even if you have a list of persons:
print([Person('a', 'b', 'c'), Person('d', 'e', 'f')])
>> [Name: a
Surname: b
Age: c, Name: d
Surname: e
Age: f]

You can take advantage of the classes' internal __dict__ property to avoid typing all of the variables twice. Additionally, it's best to use the __repr__ function for representing your class:
class Person(object):
def __init__(self, name, surname, age):
self.name = name
self.surname = surname
self.age = age
def __repr__(self):
return '\n'.join([
'Name: {name}',
'Surname: {surname}',
'Age: {age}'
]).format(**self.__dict__)
john = Person('John', 'Doe', 42)
print(john)
Another step of abstraction you could take to avoid hardcoding the format string is to create a list of the properties that identify the instance and use them as follows:
class Person(object):
_identifiers = ('name', 'surname', 'age')
def __init__(self, name, surname, age):
self.name = name
self.surname = surname
self.age = age
def __repr__(self):
return '\n'.join(
'{k}: {v}'.format(k=key.capitalize(), v=self.__dict__[key])
for key in self._identifiers
)
john = Person('John', 'Doe', 42)
print(john)

Related

How to make a list inside a class static for the entire program

I'm messing around with classes and data flow and I am having difficulties creating a list of classes inside the class (to give control of the list to the class in itself).
class Person:
listOfPeople = []
def __init__(self, name, age):
self.name = name
self.age = age
self.listOfPeople = []
def set_age(self, age):
if age <= 0:
raise ValueError('The age must be positive')
self._age = age
def get_age(self):
return self._age
def AppendList(self):
self.listOfPeople.append(self)
def returnList(self):
return self.listOfPeople
age = property(fget=get_age, fset=set_age)
john = Person('John', 18)
barry = Person("Barry", 19)
john.AppendList()
barry.AppendList()
print(Person.listOfPeople)
The output is simply
[]
Let´s use this example. I want the class Person to have a list of people. That list of people has instances of the class it's in. I want the entire program to have access to this class, regardless of having an instance initialised. Is it even possible to do what I want in Python?
My expected output is a list with the 2 instances I added to the list.
Okay so you need to create the list outside the definitions first.
Then you need to change the append function to this instead, self.listOfPeople.append(self) so that the variables are added into the list when you run it your way and remove the self.listOfPeople from the __init__.
Now the listOfPeople you initialized is shared between all instances.
class Person:
listOfPeople = []
def __init__(self, name, age):
self.name = name
self.age = age
def set_age(self, age):
if age <= 0:
raise ValueError('The age must be positive')
self._age = age
def get_age(self):
return self._age
def AppendList(self):
self.listOfPeople.append(self)
def returnList(self):
return self.listOfPeople
age = property(fget=get_age, fset=set_age)
john = Person('John', 18)
barry = Person("Barry", 19)
john.AppendList()
barry.AppendList()
print(Person.listOfPeople)
for i in Person.listOfPeople:
print (i.name, i.age)
Output for first part is:
[<__main__.Person object at 0x7fcb72395150>, <__main__.Person object at 0x7fcb723954d0>]
Output for the second part is:
John 18
Barry 19
this code automatically adds new instances to Person.listOfPeople
class Person:
listOfPeople = []
def __init__(self, name, age):
self.name = name
self.age = age
Person.listOfPeople.append(self)
def set_age(self, age):
if age <= 0:
raise ValueError('The age must be positive')
self._age = age
def get_age(self):
return self._age
def AppendList(self):
self.listOfPeople.append(self)
def returnList(self):
return self.listOfPeople
def __repr__(self): #I've added __repr__
return self.name+' '+str(self.age)
age = property(fget=get_age, fset=set_age)
john = Person('John', 18)
barry = Person("Barry", 19)
# john.AppendList()
# barry.AppendList()
print(Person.listOfPeople)
the output: [John 18, Barry 19]
is this what you need?
Just get rid of this
self.listOfPeople = []
This line overrides the class attribute and creates an instance attribute with the same name - not what you want.

How do I write a Python class taking other super class objects as parameters

Lets assume that I have a class called Person, and a class that inherits this called Group. Person has an attribute called name and one called age. When I create a Group I want to pass n person objects and their new name is a combo of names, and their new age is their combined age.
also for the hell of it, going to keep track of how many people, and how many groups there are separately (just so inheriting makes any sense in this example.)
class Person:
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
self.id = make_person() # count is also the person's id in this example
def __str__(self):
return f'Name: {self.name} Age: {self.age}'
#classmethod
def make_person(cls):
cls.count += 1
return cls.count
class Group(Person):
def __init__(self, *people):
#not sure how to do this, Below Does Not Work, something like
new_name = self.make_group(people)
new_age = self.new_age(people)
self.name = new_name
self.age = new_age
super().__init__(self.new_name, self.new_age)
def make_group(self, *people):
return (' & ').join([person.name for person in People])
def new_age(self, *people):
return sum([person.age for person in people])
then you would think i could write
anne = Person('Anne', 20)
bob = Person('Bob', 20)
carl = person('Carl', 25)
couple = Group(anne, bob)
threesome = Group(anne, bob, carl)
print(couple)
print(threesome)
but this doesnt work. For some reason the group class isnt getting the people object i pass, or i'm defining it wrong...any ideas?
What you have written is that a Group is a particular type of Person. This doesn't seem quite right to me. Regardless, here is a version that will run and give the desired output:
class Person:
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
self.id = Person.make_person() # count is also the person's id in this example
def __str__(self):
return f'Name: {self.name} Age: {self.age}'
#classmethod
def make_person(cls):
cls.count += 1
return cls.count
class Group(Person):
def __init__(self, *people):
#not sure how to do this, Below Does Not Work, something like
new_name = self.make_group(*people)
new_age = self.new_age(*people)
self.name = new_name
self.age = new_age
super().__init__(self.name, self.age)
def make_group(self, *people):
return (' & ').join([person.name for person in people])
def new_age(self, *people):
return sum([person.age for person in people])
anne = Person('Anne', 20)
bob = Person('Bob', 20)
carl = Person('Carl', 25)
couple = Group(anne, bob)
threesome = Group(anne, bob, carl)
print(couple)
print(threesome)
Changes from your code:
some typos with capital letters
put a * before people when passing it
take care of variable scope

i am setting python class but it prints <main.deteil object at 0x03391d90

i am setting python class but it prints <main.deteil object at 0x03391d90
i tried to search in google but didn't helped me
Python classes
class person:
def __init__(self,fname,lname):
self.firstname = fname
self.lastname = lname
def printname(self):
print(self.firstname, self.lastname)
class student(person):
def __init__(self,fname,lname,year):
person.__init__(self,fname,lname)
self.graduate_year = year
def welcome(self):
print("Welcome", self.firstname, self.lastname, self.graduate_year)
class dateils(person):
def __init__(self,fname,lname, age, gender,):
person.__init__(self, fname, lname)
self.age = 17
self.gender = "male"
def student_details(self):
print(self.firstname, self.lastname, self.age,self, self.gender)
#Student
x = student("Enter your name:", "Enter your lastname: ", 2019)
x.welcome()
#person details
d = dateils(input("Enter your name"), input("Enter your lastname"), input("Enter your age"), input("Enter your gender"))
d.student_details()
i expected the output of details to be entered info, but the actual output is
entered name, entered lastname, entered age, and this <main.dateils object at 0x03391D90> male
In your student_details function you print an object:
def student_details(self):
print(self.firstname, self.lastname, self.age,self, self.gender)
^
|
HERE ----------------------------------------------+
You didn't implemented __str__ and __repr__ functions inside the class so it prints the point to memory where your object is stored (it is the basic behavior). You should delete this self or replace it with self.graduate_year to print everything you want correctly.
*Note I am running python 3.6.7
As mentioned by vurmux you need a __str__ or__repr__ functions inside your class. What is happening is that python is printing out the object id <main.dateils object at 0x03391D90> which is gibberish to us. A odd way of getting around this though is shown below. I have implemented a __repr__ function where I define the instance of the class dateils (you might have meant details). Then I output the results. Also I might not sure if you meant to define self.age=17 but I left it as is and just fixed that one part.
class person:
def __init__(self,fname,lname):
self.firstname = fname
self.lastname = lname
def printname(self):
print(self.firstname, self.lastname)
class student(person):
def __init__(self,fname,lname,year):
person.__init__(self,fname,lname)
self.graduate_year = year
def welcome(self):
print("Welcome", self.firstname, self.lastname, self.graduate_year)
class dateils(person):
def __init__(self,fname,lname, age, gender,):
person.__init__(self, fname, lname)
self.age =17
self.gender = "male"
def student_details(self):
print(self.firstname, self.lastname, self.age, self.gender)
def __repr__(self):
return str(self.firstname) + str(self.lastname) + str(self.age) + str(self.gender)
#Student
x = student("Enter your name:", "Enter your lastname: ", 2019)
x.welcome()
#person details
d = dateils(input("Enter your name"), input("Enter your lastname"), input("Enter your age"), input("Enter your gender"))
d.student_details()
See the following question for more about the two str and repr
Difference between __str__ and __repr__?

Creating a class method __str__

I am working on a program that needs a str method. However, when I run the code, it only outputs:
What is the name of the pet: Tim
What type of pet is it: Turtle
How old is your pet: 6
How can I print out what I need from the str method?
Here is what I have.
This is the code for my class (classPet.py)
class Pet:
def __init__(self, name, animal_type, age):
self.__name = name
self.__animal_type = animal_type
self.__age = age
def set_name(self, name):
self.__name = name
def set_type(self, animal_type):
self.__animal_type = animal_type
def set_age(self, age):
self.__age = age
def get_name(self):
return self.__name
def get_animal_type(self):
return self.__animal_type
def get_age(self):
return self.__age
def __str__(self):
return 'Pet Name:', self.__name +\
'\nAnimal Type:', self.__animal_type +\
'\nAge:', self.__age
This is the code for my main function (pet.py):
import classPet
def main():
# Prompt user to enter name, type, and age of pet
name = input('What is the name of the pet: ')
animal_type = input('What type of pet is it: ')
age = int(input('How old is your pet: '))
pets = classPet.Pet(name, animal_type, age)
print()
main()
In the code for your main function (pet.py), you are calling print without any parameters. You need to call print with your pet instance as a parameter:
pets = classPet.Pet(name, animal_type, age)
print(pets) # see here
You also need to fix an error in your __str__ method:
the __str__ method doesn't concatenate all of its arguments to a string like the print() function does it. Instead, it must return a single string.
In your __str__ method you are seperating your different parts of the string by commas. This will make python think that it's dealing with a tuple. I propose the following solution using pythons format function:
def __str__(self):
return "Pet Name: {}\nAnimal Type: {}\nAge: {}".format(self.__name, self.__animal_type, self.__age)
The {} parts in the string are placeholders that are replaced with the arguments in the parenthesis through the format function. They are replaced in order, so the first one is replaced with self.__name, etc.

Python3 Bound method

Hi i have a python file that contains the class pets and a file conatins the class people and a main file
the code is this:
the pets code:
class Pet:
def __init__(self, name, age, sound, type):
self.name = name
self.age = age
self. sound = sound
self. type = type
class Dog(Pet):
def __init__(self, name, age):
super().__init__(name, age, "How How", "Dog")
class Cat(Pet):
def __init__(self, name, age):
super().__init__(name, age, "Mewo", "Cat")
this is the peoples file:
import Pets
class Person:
def __init__(self, gender, name, age):
self.gender = gender
self.name = name
self.age = age
self.pets = []
def addPet(self, pet):
if isinstance(pet, Pets.Pet):
self.pets.append(pet)
else:
print("This is not a pet pls try again.")
def printPets():
print("He has:")
for pet in self.pets:
print("A: " + pet.type+ " Named: " + pet.name)
And this is the Main file:
from Person import Person
import Pets
def Main():
p1 = Person("Male", "Bob", 18)
p1.addPet(Pets.Cat("Mitzi", 2))
p1.addPet(Pets.Dog("Rexi", 5))
print(p1.printPets)
if __name__ == "__main__":
Main()
the output that i get is:
<bound method Person.printPets of <Person.Person object at 0x7f413e3604e0>>
what is this and how do i fix it ??
thanx.
What you need is print(p1.printPets())
You need to invoke the method.
Else what you are doing is printing the method and what Python gives you is the method type (bound), instance type to which it belongs and address of the instance.
You just need to include () inside print() like this:
print(s1.avg())

Categories