预计阅读本页时间:-
String Representation: __repr__ and __str__
The next example exercises the __init__ constructor and the __add__ overload method, both of which we’ve already seen, as well as defining a __repr__ method that returns a string representation for instances. String formatting is used to convert the managed self.data object to a string. If defined, __repr__ (or its sibling, __str__) is called automatically when class instances are printed or converted to strings. These methods allow you to define a better display format for your objects than the default instance display.
The default display of instance objects is neither useful nor pretty:
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
>>> class adder:
... def __init__(self, value=0):
... self.data = value # Initialize data
... def __add__(self, other):
... self.data += other # Add other in-place (bad!)
...
>>> x = adder() # Default displays
>>> print(x)
<__main__.adder object at 0x025D66B0>
>>> x
<__main__.adder object at 0x025D66B0>
But coding or inheriting string representation methods allows us to customize the display:
>>> class addrepr(adder): # Inherit __init__, __add__
... def __repr__(self): # Add string representation
... return 'addrepr(%s)' % self.data # Convert to as-code string
...
>>> x = addrepr(2) # Runs __init__
>>> x + 1 # Runs __add__
>>> x # Runs __repr__
addrepr(3)
>>> print(x) # Runs __repr__
addrepr(3)
>>> str(x), repr(x) # Runs __repr__ for both
('addrepr(3)', 'addrepr(3)')
So why two display methods? Mostly, to support different audiences. In full detail:
- __str__ is tried first for the print operation and the str built-in function (the internal equivalent of which print runs). It generally should return a user-friendly display.
- __repr__ is used in all other contexts: for interactive echoes, the repr function, and nested appearances, as well as by print and str if no __str__ is present. It should generally return an as-code string that could be used to re-create the object, or a detailed display for developers.
In a nutshell, __repr__ is used everywhere, except by print and str when a __str__ is defined. Note, however, that while printing falls back on __repr__ if no __str__ is defined, the inverse is not true—other contexts, such as interactive echoes, use __repr__ only and don’t try __str__ at all:
>>> class addstr(adder):
... def __str__(self): # __str__ but no __repr__
... return '[Value: %s]' % self.data # Convert to nice string
...
>>> x = addstr(3)
>>> x + 1
>>> x # Default __repr__
<__main__.addstr object at 0x00B35EF0>
>>> print(x) # Runs __str__
[Value: 4]
>>> str(x), repr(x)
('[Value: 4]', '<__main__.addstr object at 0x00B35EF0>')
Because of this, __repr__ may be best if you want a single display for all contexts. By defining both methods, though, you can support different displays in different contexts—for example, an end-user display with __str__, and a low-level display for programmers to use during development with __repr__. In effect, __str__ simply overrides __repr__ for user-friendly display contexts:
>>> class addboth(adder):
... def __str__(self):
... return '[Value: %s]' % self.data # User-friendly string
... def __repr__(self):
... return 'addboth(%s)' % self.data # As-code string
...
>>> x = addboth(4)
>>> x + 1
>>> x # Runs __repr__
addboth(5)
>>> print(x) # Runs __str__
[Value: 5]
>>> str(x), repr(x)
('[Value: 5]', 'addboth(5)')
I should mention two usage notes here. First, keep in mind that __str__ and __repr__ must both return strings; other result types are not converted and raise errors, so be sure to run them through a converter if needed. Second, depending on a container’s string-conversion logic, the user-friendly display of __str__ might only apply when objects appear at the top level of a print operation; objects nested in larger objects might still print with their __repr__ or its default. The following illustrates both of these points:
>>> class Printer:
... def __init__(self, val):
... self.val = val
... def __str__(self): # Used for instance itself
... return str(self.val) # Convert to a string result
...
>>> objs = [Printer(2), Printer(3)]
>>> for x in objs: print(x) # __str__ run when instance printed
... # But not when instance in a list!
2
3
>>> print(objs)
[<__main__.Printer object at 0x025D06F0>, <__main__.Printer object at ...more...
>>> objs
[<__main__.Printer object at 0x025D06F0>, <__main__.Printer object at ...more...
To ensure that a custom display is run in all contexts regardless of the container, code __repr__, not __str__; the former is run in all cases if the latter doesn’t apply:
>>> class Printer:
... def __init__(self, val):
... self.val = val
... def __repr__(self): # __repr__ used by print if no __str__
... return str(self.val) # __repr__ used if echoed or nested
...
>>> objs = [Printer(2), Printer(3)]
>>> for x in objs: print(x) # No __str__: runs __repr__
...
2
3
>>> print(objs) # Runs __repr__, not ___str__
[2, 3]
>>> objs
[2, 3]
In practice, __str__ (or its low-level relative, __repr__) seems to be the second most commonly used operator overloading method in Python scripts, behind __init__. Any time you can print an object and see a custom display, one of these two tools is probably in use.