0

I have a class which initialises a person, then another class to handle the manipulation and displaying of that persons details. When I try to use the display_person method it prints the class instance rather than the fullname. I tried adding dunder methods __str__ and __repr__ however that doesn't resolve it.

import itertools

class Person:

    num_of_emps = 0
    id_iter = itertools.count(1)

    def __init__(self, firstname: str, surname: str, address: str, email: str):
        self.firstname = str(firstname)
        self.surname = str(surname)
        self.fullname = str(firstname) + ' ' + str(surname)
        self.email = str(email)
        self.address = str(address)

        person_id = next(self.id_iter)
        self.person_id = int(person_id)
        Person.num_of_emps += 1


class PersonActions:
    def display_person(self, fullname) -> None:
        print(f'This is {fullname.__str__()}.')

p1 = Person('Lucas', 'S', '100 st', 'lucasshaw@email.com')
p2 = Person('Rosie', 'B', '101 st', 'rosiebryan@email.com')
action = PersonActions()
print(action.display_person(p1))

The output is:

This is <__main__.Person object at 0x10aeebe20>.
None.

Would the architecture be better if I added the display_person method to the Person class directly? From research I have seen that its better to keep these methods separate for cohesion purposes as per this. How can I get the display_person method to print the full name? I plan to do the same with other details later on.

Why does it print 'None' also?

I have looked at class employee print method but still can't figure it out.

Barmar
  • 741,623
  • 53
  • 500
  • 612
Luca
  • 97
  • 7
  • 1
    It prints `None` also because in addition to printing within `display_person` you *also* print the return value of that function. "I have a class which initialises a person, then another class to handle the manipulation and displaying of that persons details." this is a bizarre separation of duties, fwiw. – erik258 Oct 02 '22 at 17:07
  • Please show your `__str__()` method, that should have worked. – Barmar Oct 02 '22 at 17:08

3 Answers3

2

You pass in an instance of Person, so you should handle it as such in your other class:

class PersonActions:
    def display_person(self, person) -> None:
        print(f'This is {person.fullname.__str__()}.')

Actually you don't need the .__str()__, nor do you need the print() when you are calling this method:

class PersonActions:
    def display_person(self, person) -> None:
        print(f'This is {person.fullname}.')

p1 = Person('Lucas', 'S', '100 st', 'lucasshaw@email.com')
p2 = Person('Rosie', 'B', '101 st', 'rosiebryan@email.com')
action = PersonActions()
action.display_person(p1)

Update:

or you meant to include a __str__() method like this:

class Person:
    ...   # Current implementation elided - see code from OP
    def __str__(self):
        return self.fullname

class PersonActions:
    def display_person(self, person) -> None:
        print(f'This is {person}.')

The f-string formatting will automatically call the __str__() method for you.

quamrana
  • 37,849
  • 12
  • 53
  • 71
  • I think he wants printing a `Person` to automatically show the `fullname`, using a `__str__()` method. – Barmar Oct 02 '22 at 17:10
  • Thank you, I didn't know f-string called the __str__. To clarify, I plan to include more methods to show the other details of the Person (ie, id, email, address) so `{person.fullname}` is ideal – Luca Oct 03 '22 at 11:08
  • @Barmar yes I might end up just printing all Person details within a single function so that is also an option – Luca Oct 03 '22 at 11:10
1

Defining the __str__() method should work:

class Person:

    num_of_emps = 0
    id_iter = itertools.count(1)

    def __init__(self, firstname: str, surname: str, address: str, email: str):
        self.firstname = str(firstname)
        self.surname = str(surname)
        self.fullname = str(firstname) + ' ' + str(surname)
        self.email = str(email)
        self.address = str(address)

        person_id = next(self.id_iter)
        self.person_id = int(person_id)
        Person.num_of_emps += 1

    def __str__(self):
        return self.fullname

class PersonActions:
    def display_person(self, person: Person) -> None:
        print(f'This is {person}.')

You don't need to call .__str__() explicitly. The f-string converts the values to strings automatically.

Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Add this to your class:

  def __str__(self):
        return(f"{self.fullname}")

and then print(p1)

Elicon
  • 206
  • 1
  • 11