预计阅读本页时间:-
Providing Print Displays
Fortunately, it’s easy to do better by employing operator overloading—coding methods in a class that intercept and process built-in operations when run on the class’s instances. Specifically, we can make use of what is probably the second most commonly used operator overloading method in Python, after __init__: the __str__ method introduced in the preceding chapter. __str__ is run automatically every time an instance is converted to its print string. Because that’s what printing an object does, the net transitive effect is that printing an object displays whatever is returned by the object’s __str__ method, if it either defines one itself or inherits one from a superclass (double-underscored names are inherited just like any other).
Technically speaking, the __init__ constructor method we’ve already coded is operator overloading too—it is run automatically at construction time to initialize a newly created instance. Constructors are so common, though, that they almost seem like a special case. More focused methods like __str__ allow us to tap into specific operations and provide specialized behavior when our objects are used in those contexts.
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
Let’s put this into code. The following extends our class to give a custom display that lists attributes when our class’s instances are displayed as a whole, instead of relying on the less useful default display:
# Add __str__ overload method for printing objects
class Person:
def __init__(self, name, job=None, pay=0):
self.name = name
self.job = job
self.pay = pay
def lastName(self):
return self.name.split()[-1]
def giveRaise(self, percent):
self.pay = int(self.pay * (1 + percent))
def __str__(self): # Added method
return '[Person: %s, %s]' % (self.name, self.pay) # String to print
if __name__ == '__main__':
bob = Person('Bob Smith')
sue = Person('Sue Jones', job='dev', pay=100000)
print(bob)
print(sue)
print(bob.lastName(), sue.lastName())
sue.giveRaise(.10)
print(sue)
Notice that we’re doing string % formatting to build the display string in __str__ here; at the bottom, classes use built-in type objects and operations like these to get their work done. Again, everything you’ve already learned about both built-in types and functions applies to class-based code. Classes largely just add an additional layer of structure that packages functions and data together and supports extensions.
We’ve also changed our self-test code to print objects directly, instead of printing individual attributes. When run, the output is more coherent and meaningful now; the “[...]” lines are returned by our new __str__, run automatically by print operations:
[Person: Bob Smith, 0]
[Person: Sue Jones, 100000]
Smith Jones
[Person: Sue Jones, 110000]
Here’s a subtle point: as we’ll learn in the next chapter, a related overloading method, __repr__, provides an as-code low-level display of an object when present. Sometimes classes provide both a __str__ for user-friendly displays and a __repr__ with extra details for developers to view. Because printing runs __str__ and the interactive prompt echoes results with __repr__, this can provide both target audiences with an appropriate display. Since we’re not interested in displaying an as-code format, __str__ is sufficient for our class.