better than the default display we get for an instanceclass persondef __str__(self)return % >(self __class__ __name__self nametom manager('tom jones' print(tomprintstom joneshere __class__ gives the lowest class from which self was madeeven though __str__ may be inherited the net effect is that __str__ allows us to print instances directly instead of having to print specific attributes we could extend this __str__ to loop through the instance' __dict__ attribute dictionary to display all attributes genericallyfor this preview we'll leave this as suggested exercise we might even code an __add__ method to make expressions automatically call the giveraise method whether we should is another questionthe fact that expression gives person raise might seem more magical to the next person reading our code than it should constructor customization finallynotice that we didn' pass the job argument when making manager in example - if we hadit would look like this with keyword argumentstom manager(name='tom doe'age= pay= job='manager'the reason we didn' include job in the example is that it' redundant with the class of the objectif someone is managertheir class should imply their job title instead of leaving this field blankthoughit may make more sense to provide an explicit constructor for managerswhich fills in this field automaticallyclass manager(person)def __init__(selfnameagepay)person __init__(selfnameagepay'manager'now when manager is createdits job is filled in automatically the trick here is to call to the superclass' version of the method explicitlyjust as we did for the giveraise method earlier in this sectionthe only difference here is the unusual name for the constructor method alternative classes we won' use any of this section' three extensions in later examplesbut to demonstrate how they workexample - collects these ideas in an alternative implementation of our person classes sneak preview