Do I need to define __repr__() ?

  • Python
  • Thread starter m4r35n357
  • Start date
In summary: I believe that every class should have a __str__ method and leave __repr__ to be used when needed (generally when generating a string representation of the object).THe author suggests that every class should have one. In contrast, I have written many python programs in 2.x and 3.x form and never once needed to...define __repr__(). I believe that every class should have a __str__ method and leave __repr__ to be used when needed (generally when generating a string representation of the object).
  • #1
m4r35n357
654
148
[TLDR] what terrible things will happen if I don't?

I've been searching this for a while and all I have found are various "explanations" that __repr__() should provide an "official" representation of the object (or is it class, or instance?). Also it should be usable as input to eval() - (to construct an instance I suppose . . . ?). The documentation I have seen on the matter assumes that the user already knows what it is for ;)

Anyhow, I have not yet encountered a situation that causes me to believe that I need to define it. Perhaps the use case just doesn't apply to what I am doing (number crunching).
Python:
class Series:

    def __init__(self, jet, diff=False):
        self.jet = jet
        self.n = len(self.jet)
        if diff:
            self.jet[1] = D1
        self.diff_status = diff
Here, jet is a list of floats, diff is a bool, and n in an int. So, is __repr__() supposed to make a string "constructor call" for eval? If so, how should I proceed?
 
Technology news on Phys.org
  • #2
No you don’t need to define it. It’s for special cases to generate eval() runnable code ie a program writing a program to run except you’re writing an expression / command for eval to run.

https://www.geeksforgeeks.org/str-vs-repr-in-python/

A fun example is to write a recursive expression that runs itself rather like a mirrror reflecting off itself to infinity.
 
  • Like
Likes m4r35n357
  • #3
Cheers, I'm glad you said that ;)
 
  • #4
It's meant for defining a default print representation for your object -- if you want one. This is what you see if you evaluate an object at the REPL. Most of the built-in types in Python have a print representation that is simply what you would type to create the object, e.g.:
Python:
>>> 3
3
>>> 'hello'
'hello'
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
An exception is functions. They don't have a defined print representation so instead you see generic output telling you the object type and a memory address:
Python:
>>> f = lambda x: x**2
>>> f
<function <lambda> at 0x7f387d33c730>
For object types you define yourself, you'll see output like that unless you create a __repr__ method to print something different. Normally, if you do that, you're supposed to print actual code that could be copied and pasted into the REPL to create the object, if it's sensible to do so. (Notice how the print representation for the string above includes the quotes, for example.) The Fraction class in the standard library shows an example of this:
Python:
>>> from fractions import Fraction
>>> Fraction(1, 2) + Fraction(3, 4)
Fraction(5, 4)
That print output is decided by a __repr__ method defined (in Python 2) like this:
Python:
    def __repr__(self):
         """repr(self)"""
         return ('Fraction(%s, %s)' % (self._numerator, self._denominator))
 
  • #5
wle said:
Python:
    def __repr__(self):
         """repr(self)"""
         return ('Fraction(%s, %s)' % (self._numerator, self._denominator))

Ah, so it is a "constructor call" then. I use __str__() to dump the information that I want (i.e. not all of it!), and that is sufficient. The docs seemed to imply that I should be using __repr__(), but I didn't get why. Thanks for the clarification.
 
  • #6
m4r35n357 said:
Ah, so it is a "constructor call" then.

No, it isn't. The constructor for an instance of a class is __init__. __repr__ is just a "special method", which is basically a method that can get called implicitly by the interpreter under certain circumstances (in this case, by calling the repr() built-in function or if a string representation of the object is needed and it has no __str__ method defined).
 
  • #7
PeterDonis said:
No, it isn't. The constructor for an instance of a class is __init__. __repr__ is just a "special method", which is basically a method that can get called implicitly by the interpreter under certain circumstances (in this case, by calling the repr() built-in function or if a string representation of the object is needed and it has no __str__ method defined).
What I meant was the output of __repr__ is supposed to be the text of a constructor call, not the __repr__ method itself. This was the information I could not extract from the docs.
 
  • #8
The output of repr() is supposed to be code that eval() can evaluate to print it.

https://www.tutorialspoint.com/What-does-the-repr-function-do-in-Python-Object-Oriented-Programming

While str() mght output "hello" then repr would output print("hello");

It allows a python program to write a python program.

Here's a contrarian view on repr() for a class:

https://www.pythoncentral.io/what-is-the-difference-between-__str__-and-__repr__-in-python/

THe author suggests that every class should have one. In contrast, I have written many python programs in 2.x and 3.x form and never once needed to write a repr function but I can see its utility. However, I don't think every class needs one only those that you might like to use in the manner I described earlier.
 
  • #9
jedishrfu said:
While str() mght output "hello" then repr would output print("hello");

It allows a python program to write a python program.

Further clarification, thanks! I am sure now it is not for me, as I do mostly number crunching and don't use the evil() function ;)
 
  • #10
m4r35n357 said:
Ah, so it is a "constructor call" then.

Not always. __repr__() is the method used by the interpreter to decide how to print objects. The idea is it should use the same syntax that you would in source code. It's useful if you want to use Python interactively or for interactive testing and debugging. You can see the objects and you can copy the output made by __repr__() and paste it back into the interpreter or into a source code file. It's also useful if you want to save objects in a text format (e.g. to save to a text file or send over a network connection) that you can read back into Python later.

Eval is used to define what it should do (it should work such that eval(repr(x)) == x). That does not mean this is how it is actually expected to be used.

An example where __repr__() is really useful but is bending the guideline a little is the output generated for symbolic objects in SymPy. The fact that they have __repr__() methods is what allows you to use Python with SymPy as an interactive calculator, similar to how you normally use tools like Mathematica or Matlab:
Python:
>>> from sympy import symbols, expand
>>> x, y = symbols('x y')
>>> expand((x + y)**3)
x**3 + 3*x**2*y + 3*x*y**2 + y**3
You could copy and paste that last line back in as input to the Python interpreter, but only if you've previously done x, y = symbols('x y').

But no, you don't always need this and your class will work fine without a __repr__() method.
jedishrfu said:
The output of repr() is supposed to be code that eval() can evaluate to print it.

https://www.tutorialspoint.com/What-does-the-repr-function-do-in-Python-Object-Oriented-Programming

While str() mght output "hello" then repr would output print("hello");

repr() returns a string that is supposed to be code to create the object, not to print it. For a string, repr() just returns the same string but with extra quote characters at the beginning and end and extra backslashes if necessary:
Python:
>>> 'hello'
'hello'
>>> repr('hello')
"'hello'"
>>> repr(repr('hello'))
'"\'hello\'"'
>>> repr(repr(repr('hello')))
'\'"\\\'hello\\\'"\''
 
  • #11
jedishrfu said:
The output of repr() is supposed to be code that eval() can evaluate to print it.

No, not to print it. The output of __repr__ is supposed to be code that eval() can evaluate to return a Python object that is the same as the one whose __repr__ was invoked.

jedishrfu said:
While str() mght output "hello" then repr would output print("hello");

No, the __repr__ of a string does not output "print". It just outputs the string with quotes around it.
 
  • #12
m4r35n357 said:
Further clarification, thanks!

His clarification is wrong. See posts #10 and #11.

m4r35n357 said:
What I meant was the output of __repr__ is supposed to be the text of a constructor call

If you want __repr__ to output a string that eval() can evaluate to construct an object that's the same as the one whose __repr__ was called, yes. For some objects, this is not really needed or feasible; those are the cases where __repr__ just gives you a string like <object object at ...>.

Also note that this only really applies to instances of user-defined classes. Instances of built-in classes such as strings don't need to have their __repr__ output an explicit constructor call, because the interpreter already has syntactic support for them built in. That's why, for example, the __repr__ of a string just outputs the string with quotes around it, not a call to the str() class constructor.
 
  • #13
wle said:
It's meant for defining a default print representation for your object -- if you want one.

This is a common use (since it's built into the interpreter), but not the only possible one. That's why it's better to describe __repr__ as returning a string that eval() can use to construct the object (as you and I have in more recent posts); this is a general description that applies to any use case, not just printing at the REPL.
 
  • #14
PeterDonis said:
No, the __repr__ of a string does not output "print". It just outputs the string with quotes around it.

My apologies here, I found one example that did that to show what repr(0 could be used for and took it to mean that that was its proper function.

Later examples such as the datetime.now illustrate repr() usage better in the python REPL:

Python:
import datetime

today = datetime.datetime.now()

repr(today)

outputting:

Code:
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'
 

1. What is the purpose of defining __repr__() in a class?

The __repr__() method is used to define a string representation of an object. This string representation is used when the object needs to be printed or converted into a string. It helps to provide a concise and informative representation of the object.

2. Do I need to define __repr__() for every class I create?

No, you do not need to define __repr__() for every class you create. It is an optional method and is only necessary if you want a specific string representation for your object. If you do not define __repr__(), the default string representation will be used.

3. Can __repr__() and __str__() be used interchangeably?

No, they cannot be used interchangeably. __str__() is used to provide a human-readable string representation of an object, while __repr__() is used to provide a unambiguous string representation of an object. They serve different purposes and should be defined accordingly.

4. Is it possible to customize the output of __repr__()?

Yes, it is possible to customize the output of __repr__() by defining the method in your class. You can choose what information you want to include in the string representation and how it is formatted.

5. Can __repr__() be used for debugging purposes?

Yes, __repr__() can be useful for debugging purposes as it provides a detailed and unambiguous representation of an object. This can help in identifying and resolving any issues with the object. However, it is recommended to use __repr__() for its intended purpose of providing a string representation of an object.

Similar threads

  • Programming and Computer Science
Replies
2
Views
2K
  • Programming and Computer Science
Replies
10
Views
10K
  • STEM Academic Advising
Replies
5
Views
1K
Back
Top