Saswata Mishra
Saswata Mishra

Reputation: 111

Can't getting the implementation of __repr__() method in python

I was reading the famous book on python named 'python cookbook' by David Beazley and Brian K. Jones. In their 'classes and objects' chapter, they have written the following code:

class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def __repr__(self):
        return 'Point({0.x!r}, {0.y!r})'.format(self)
    def __str__(self):
        return '({0.x!s}, {0.y!s})'.format(self)

Now, only I got to understand that the repr() method is used to represent an object to a developer and str() to a blind user. But in both the methods, what is being happened after 'return'? There are tuples in both cases for sure. But what kinda member the tuples have? I haven't seen anything like this before.

Upvotes: 3

Views: 417

Answers (3)

a_guest
a_guest

Reputation: 36249

Here's a breakdown of the specific formatting syntax. With the str.format method you can fill-in placeholders in the given string instance that are of the form {...}. These work with positional arguments in the following way:

>>> '{}:{}'.format(1, 2)
'1:2'
>>> '{0}:{1}'.format(1, 2)
'1:2'
>>> '{1}:{0}'.format(1, 2)
'2:1'

That means you can specify the number of the positional argument inside the curly braces. The string can refer to a positional argument multiple times:

>>> '{0}:{1}:{0}'.format(1, 2)
'1:2:1'

Using .x notation let's you access attributes of that argument. For example:

>>> class Test:
...     x = 1
...     y = 2
... 
>>> '{0.x}:{0.y}'.format(Test)
'1:2'

Using !r you can force to use the __repr__ of that object rather than the __str__. For example:

>>> class Test:
...     def __str__(self):
...         return '__str__'
...     def __repr__(self):
...         return '__repr__'
... 
>>> '{0}'.format(Test())
'__str__'
>>> '{0!s}'.format(Test())
'__str__'
>>> '{0!r}'.format(Test())
'__repr__'

So combining all this information we get the following:

'Point({0.x!r}, {0.y!r})'.format(self)

Here a format string with two placeholders is defined ({0.x!r} and {0.y!r}). They should be filled in with the first positional argument's x and y attributes (recall that {0} will be substituted with the first argument, so {0.x} requests the x attribute of that argument). And finally the !r requests the __repr__ of that object rather than the __str__ (which is the default).

The same reasoning applies to the __str__ method.

By the way, the formatting syntax also allows keyword arguments and they can be referred to by their name:

>>> '{first}:{second}'.format(first=1, second=2)
'1:2'
>>> '{second}:{first}'.format(first=1, second=2)
'2:1'

Upvotes: 1

Noctis Skytower
Noctis Skytower

Reputation: 22001

You might want to try this in an interpreter to see what is going on:

>>> class Point:
    def __init__(self, x, y):
        """Initialize self."""
        self.x, self.y = x, y
    def __repr__(self):
        """Return repr(self)."""
        return f'{type(self).__name__}({self.x!r}, {self.y!r})'
    def __str__(self):
        """Return str(self)."""
        return f'({self.x!s}, {self.y!s})'

>>> Point(1, 2) # causes implicit call to __repr__
Point(1, 2)
>>> print(_) # causes implicit call to __str__
(1, 2)
>>> 

Upvotes: 0

Ofer Sadan
Ofer Sadan

Reputation: 11922

Both __repr__ and __str__ in your example return formatted strings, not tuples. These functions are called when either repr() or str() is called on the object, explicitly or implicitly.

For example, a print(Point(1,2)) would print the result of __str__ because it calls str() on the object internally, but print([Point(1,2)]) would print the result of __repr__ instead.

For your own objects, these methods can return anything you want, just as long as those are just strings.

Upvotes: 2

Related Questions