Is thre a better way to build it so it print all attributes from class/parent-class
<p>I have a <code>Student</code> class extending <code>Person</code> class, both class implemented <code>__str__</code> to list out all attributes in both <code>Person</code> and <code>Student</code> class. </p>

<p>However, I am having issues with trying to do a print of <code>__str__</code> in the <code>__init__</code> function as below. </p>

<pre><code>class Person(object):
    def __init__(self, n):
        self.name = n
        print Person.__str__(self)

    def __str__(self):
        return "%15s%s\n" % ("Name: ", self.name)

class Student(Person):
    def __init__(self, n, sid, d):
        Person.__init__(self,n)
        self.sid = sid
        self.degree = d
        print Student.__str__(self)

    def __str__(self):
        return Person.__str__(self) + "%15s%s\n%15s%s\n"  % ("StudentID: ", self.sid, "Degree: ", self.degree)
</code></pre>

<p>When I execute the following</p>

<pre><code>Jeff = Person("Jeff")
Cameron = Student('Cameron', 'U2314313', "Social Science")
</code></pre>

<p>it would produce something like:</p>

<pre><code>Name: Jeff
Name: Cameron
Name: Cameron
StudentID:......
Degree:......
</code></pre>

<p>When initializing <code>Student</code>, it's calling <code>Student.__str__(self)</code>, and subsequently call <code>Person.__str__(self)</code> in order to bring back the name. </p>

<p>Just wondering if there's a better way to build the the structure so it's more usable and inline with the OO concept. </p>

<p>The result that I want is when I do the <code>__str__</code> for both <code>Student</code> or <code>Person</code>, it would list out all attributes, such as:</p>

<pre><code>Name: Jeff
Name: Cameron
StudentID:......
Degree:......
</code></pre>

<p>and when I do something like <code>print Cameron</code>, it would still give me </p>

<pre><code>Name: Cameron
StudentID:......
Degree:......
</code></pre>

<p>I know my code is duplicating it at the moment, but I can't figure out a way to make it work the way I intended... Help please. </p>

<p>Yes there is. Use <a href="https://docs.python.org/3.5/library/functions.html#super" rel="nofollow"><code>super</code></a> which calls "parent's" function realization. I'm quoting parent because it is little different than in other programming languages. There is awesome presentation by Raymond Hettinger on Pycon 2015 <a href="https://www.youtube.com/watch?v=EiOglTERPEo" rel="nofollow">https://www.youtube.com/watch?v=EiOglTERPEo</a>.</p>

<pre><code>class Person(object):
    def __init__(self, n):
        self.name = n
        print self.__str__()

    def __str__(self):
        return "%15s%s\n" % ("Name: ", self.name)

class Student(Person):
    def __init__(self, n, sid, d):
        Person.__init__(self,n)
        self.sid = sid
        self.degree = d
        print self.__str__()

    def __str__(self):
        return super().__str__() + "%15s%s\n%15s%s\n"  % ("StudentID: ", self.sid, "Degree: ", self.degree)
</code></pre>

<p>Here as you see when we need to call method of current class we just do <code>self.method()</code>, but if we need to call parent method we do <code>super().method()</code></p>

<p>And i would suggest using <a href="https://docs.python.org/3.5/library/stdtypes.html#str.format" rel="nofollow"><code>format</code></a> for string formating because it is more clear and readable.</p>

<pre><code>class Person(object):
    def __init__(self, n):
        self.name = n
        print self.__str__()

    def __str__(self):
        return "Name: {}\n".format(self.name)

class Student(Person):
    def __init__(self, n, sid, d):
        Person.__init__(self,n)
        self.sid = sid
        self.degree = d
        print self.__str__()

    def __str__(self):
        return super().__str__() + "StudentID: {}\nDegree: {}\n".format(self.sid, self.degree)
</code></pre>

python class oop initialization