[Tutor] __str__ on a subclass

Peter Otten __peter__ at web.de
Tue Jun 20 02:41:05 EDT 2017


Evuraan wrote:

> Greetings!
> 
> 
> #!/usr/bin/python3
> class Employee:
>         """Class with FirstName, LastName, Salary"""
>         def __init__(self, FirstName,LastName, Salary):
>                 self.FirstName = FirstName
>                 self.LastName = LastName
>                 self.Salary = Salary
>         def __str__(self):
>                 return '("{}" "{}" "{}")'.format(self.FirstName,
> self.LastName, self.Salary)
> class Developer(Employee):
>         """Define a subclass, augment with ProgLang"""
>         def __init__(self, FirstName,LastName, Salary, ProgLang):
>                 Employee.__init__(self, FirstName,LastName, Salary)
>                 self.ProgLang = ProgLang
>         def dev_repr(self):
>                 return '("{}" "{}" "{}" "{}")'.format(self.FirstName,
> self.LastName, self.Salary, self.ProgLang)
> a = Employee("Abigail", "Buchard", 83000)
> print(a)
> dev_1 = Developer("Samson", "Sue", 63000, "Cobol",)
> print(dev_1)
> print(dev_1.dev_repr())
> 
> running that yields,
> 
> ("Abigail" "Buchard" "83000")
> ("Samson" "Sue" "63000")
> ("Samson" "Sue" "63000" "Cobol")
> 
> My doubt is, how can we set the  __str__ method work on the Employee
> subclass so that it would show ProgLang too, like the
> print(dev_1.dev_repr())?
> 
> Thanks in advance!

Here's an indirect approach that should be easy to understand and adapt -- 
provide a method that converts attributes into a tuple. Subclasses that 
introduce new attributes can override this method, and __str__() uses 
as_tuple() to get the instance data instead of accessing the attributes 
directly:

$ cat tmp.py
#!/usr/bin/python3


def quote(value):
    # have you thought about attributes containing a '"'?
    return '"{}"'.format(value)


class Employee:
    """Class with FirstName, LastName, Salary"""
    def __init__(self, FirstName, LastName, Salary):
        self.FirstName = FirstName
        self.LastName = LastName
        self.Salary = Salary

    def as_tuple(self):
        return self.FirstName, self.LastName, self.Salary

    def __str__(self):
        strings = (quote(a) for a in self.as_tuple())
        return "({})".format(" ".join(strings))


class Developer(Employee):
    """Define a subclass, augment with ProgLang"""
    def __init__(self, FirstName, LastName, Salary, ProgLang):
        super().__init__(FirstName, LastName, Salary)
        self.ProgLang = ProgLang

    def as_tuple(self):
        return super().as_tuple() + (self.ProgLang,)


print(Employee("Abigail", "Buchard", 83000))
print(Developer("Samson", "Sue", 63000, "Cobol"))
$ python3 tmp.py
("Abigail" "Buchard" "83000")
("Samson" "Sue" "63000" "Cobol")

Another option builds on the assumption that attribute names match __init__ 
argument names (I've replaced quote() with repr() this time):

$ cat tmp2.py
#!/usr/bin/python3
import inspect


class Employee:
    """Class with FirstName, LastName, Salary"""
    def __init__(self, FirstName, LastName, Salary):
        self.FirstName = FirstName
        self.LastName = LastName
        self.Salary = Salary

    def __str__(self):
        names = inspect.getargspec(self.__init__).args[1:]
        values = (getattr(self, name) for name in names)
        return "({})".format(" ".join(map(repr, values)))


class Developer(Employee):
    """Define a subclass, augment with ProgLang"""
    def __init__(self, FirstName, LastName, Salary, ProgLang):
        super().__init__(FirstName, LastName, Salary)
        self.ProgLang = ProgLang


print(Employee("Abigail", "Buchard", 83000))
print(Developer("Samson", "Sue", 63000, "Cobol"))
$ python3 tmp2.py
('Abigail' 'Buchard' 83000)
('Samson' 'Sue' 63000 'Cobol')




More information about the Tutor mailing list