Search code examples
pythonstringrepr

Why are str(repr(p)) and print(repr(p)) not the same?


I've read in this thread all the answers, but I got stuck in the following example:

Example:

class Person:
     pass

p=Person()

According to this source, if you call repr(p) you will get this as default:

<__main__.Person object at 0x7fb2604f03a0>

However, I called repr(p) on the python shell and I got this:

>>> repr(p)
'<__main__.Person object at 0x000001F1C0B1A2E0>'

As far as my understanding goes, there's a huge difference between the both: the latter is python expression, in this way, it can be used in eval().

Because I got two different results, I tried to pin down the cause, which I think I did.

>>>print(repr(p))
<__main__.Person object at 0x0000021D032392E0>

According to the documentation, object.__str__(self) is called when you use str(object) and print(object), so I tried this:

x = print(repr(p))
y = str(repr(p))
>>> x == y
False

Comparison:

>>> print(repr(p))
<__main__.Person object at 0x0000021D032392E0>
>>> str(repr(p))
'<__main__.Person object at 0x0000021D032392E0>'

From this answer,

In the Python shell (interactive interpreter), if you enter a variable at the >>> prompt and press RETURN, the interpreter displays the results of repr() implicitly called on that object.

repr() is being called behind the scenes, meaning that, on the python shell, >>> p returns repr(p).

<__main__.Person object at 0x000002184030A2E0>

>>> repr(p) returns repr(repr(p)), that is, repr(<__main__.Person object at 0x000002184030A2E0>).

'<__main__.Person object at 0x000002184030A2E0>'

However, I'm not sure why print(repr(p)) and str(repr(p)) differ on the python shell, don't they both call the same function?


Solution

  • The main point of confusion here is around how print and the REPL work. You can eliminate repr from the situation entirely and just use string literals to observe when you see the quotes and when you don't:

    >>> "foo"
    'foo'
    >>> print("foo")
    foo
    >>> x = print("foo")
    foo
    >>> x
    >>> x is None
    True
    

    When you see 'foo', it's the REPL showing you the (eval-able) value of the string expression you just typed in. When you see foo without the quotes, it's a side effect of having called print, which prints the actual contents of the string. print also returns None, as demonstrated by evaluating x is None after assigning its result to x. Note that the REPL does not echo None to the console when it evaluates an expression that returns None.