Understanding Repr( ) Function in Python

Understanding repr( ) function in Python

>>> x = 'foo'
>>> x
'foo'

So the name x is attached to 'foo' string. When you call for example repr(x) the interpreter puts 'foo' instead of x and then calls repr('foo').

>>> repr(x)
"'foo'"
>>> x.__repr__()
"'foo'"

repr actually calls a magic method __repr__ of x, which gives the string containing the representation of the value 'foo' assigned to x. So it returns 'foo' inside the string "" resulting in "'foo'". The idea of repr is to give a string which contains a series of symbols which we can type in the interpreter and get the same value which was sent as an argument to repr.

>>> eval("'foo'")
'foo'

When we call eval("'foo'"), it's the same as we type 'foo' in the interpreter. It's as we directly type the contents of the outer string "" in the interpreter.

>>> eval('foo')

Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
eval('foo')
File "<string>", line 1, in <module>
NameError: name 'foo' is not defined

If we call eval('foo'), it's the same as we type foo in the interpreter. But there is no foo variable available and an exception is raised.

>>> str(x)
'foo'
>>> x.__str__()
'foo'
>>>

str is just the string representation of the object (remember, x variable refers to 'foo'), so this function returns string.

>>> str(5)
'5'

String representation of integer 5 is '5'.

>>> str('foo')
'foo'

And string representation of string 'foo' is the same string 'foo'.

Can someone explain how to use the repr function to format the output?

The repr function is inteded to return "printable object representations", possibly for use with the eval function to construct the object back from it's string representation. But repr doesn't do any formatting itself, it just calls the __repr__ method on the object, which may be some default Python implementation or your implementation on your objects.

In your case, when you call repr on a list, it just returns quoted list output, as that's how repr is implemented for the list object:

>>> data = [['Tier', 'Weights', 'Price', 'Number of Businesses', 'Revenue'], ['Tier 1', 0.2, 180, 40000.0, 7200000.0], ['Tier 2', 0.1, 300, 20000.0, 6000000.0], ['Tier 3', 0.3, 450, 60000.0, 27000000.0], ['Tier 4', 0.15, 600, 30000.0, 18000000.0], ['Tier 5', 0.2, 750, 40000.0, 30000000.0]]
>>> repr(data)
"[['Tier', 'Weights', 'Price', 'Number of Businesses', 'Revenue'], ['Tier 1', 0.2, 180, 40000.0, 7200000.0], ['Tier 2', 0.1, 300, 20000.0, 6000000.0], ['Tier 3', 0.3, 450, 60000.0, 27000000.0], ['Tier 4', 0.15, 600, 30000.0, 18000000.0], ['Tier 5', 0.2, 750, 40000.0, 30000000.0]]"

The repr example you provide is actually nothing more than just a manual formatting. repr in this case is only used to get a string representation of the integer x to be able to call string.rjust formatting function on it:

>>> repr(1)
'1'
>>> repr(1).rjust(3)
' 1'

As for your case, you could use the pprint module intended for Python data structures pretty-printing. The pprint.pprint function actually behaves almost exactly as you want:

>>> data = [['Tier', 'Weights', 'Price', 'Number of Businesses', 'Revenue'], ['Tier 1', 0.2, 180, 40000.0, 7200000.0], ['Tier 2', 0.1, 300, 20000.0, 6000000.0], ['Tier 3', 0.3, 450, 60000.0, 27000000.0], ['Tier 4', 0.15, 600, 30000.0, 18000000.0], ['Tier 5', 0.2, 750, 40000.0, 30000000.0]]
>>> import pprint
>>> pprint.pprint(data)
[['Tier', 'Weights', 'Price', 'Number of Businesses', 'Revenue'],
['Tier 1', 0.2, 180, 40000.0, 7200000.0],
['Tier 2', 0.1, 300, 20000.0, 6000000.0],
['Tier 3', 0.3, 450, 60000.0, 27000000.0],
['Tier 4', 0.15, 600, 30000.0, 18000000.0],
['Tier 5', 0.2, 750, 40000.0, 30000000.0]]

But if you need something very specific, you may need to roll your own printing.

What is the difference between __str__ and __repr__?

Alex summarized well but, surprisingly, was too succinct.

First, let me reiterate the main points in Alex’s post:

  • The default implementation is useless (it’s hard to think of one which wouldn’t be, but yeah)
  • __repr__ goal is to be unambiguous
  • __str__ goal is to be readable
  • Container’s __str__ uses contained objects’ __repr__

Default implementation is useless

This is mostly a surprise because Python’s defaults tend to be fairly useful. However, in this case, having a default for __repr__ which would act like:

return "%s(%r)" % (self.__class__, self.__dict__)

would have been too dangerous (for example, too easy to get into infinite recursion if objects reference each other). So Python cops out. Note that there is one default which is true: if __repr__ is defined, and __str__ is not, the object will behave as though __str__=__repr__.

This means, in simple terms: almost every object you implement should have a functional __repr__ that’s usable for understanding the object. Implementing __str__ is optional: do that if you need a “pretty print” functionality (for example, used by a report generator).

The goal of __repr__ is to be unambiguous

Let me come right out and say it — I do not believe in debuggers. I don’t really know how to use any debugger, and have never used one seriously. Furthermore, I believe that the big fault in debuggers is their basic nature — most failures I debug happened a long long time ago, in a galaxy far far away. This means that I do believe, with religious fervor, in logging. Logging is the lifeblood of any decent fire-and-forget server system. Python makes it easy to log: with maybe some project specific wrappers, all you need is a

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

But you have to do the last step — make sure every object you implement has a useful repr, so code like that can just work. This is why the “eval” thing comes up: if you have enough information so eval(repr(c))==c, that means you know everything there is to know about c. If that’s easy enough, at least in a fuzzy way, do it. If not, make sure you have enough information about c anyway. I usually use an eval-like format: "MyClass(this=%r,that=%r)" % (self.this,self.that). It does not mean that you can actually construct MyClass, or that those are the right constructor arguments — but it is a useful form to express “this is everything you need to know about this instance”.

Note: I used %r above, not %s. You always want to use repr() [or %r formatting character, equivalently] inside __repr__ implementation, or you’re defeating the goal of repr. You want to be able to differentiate MyClass(3) and MyClass("3").

The goal of __str__ is to be readable

Specifically, it is not intended to be unambiguous — notice that str(3)==str("3"). Likewise, if you implement an IP abstraction, having the str of it look like 192.168.1.1 is just fine. When implementing a date/time abstraction, the str can be "2010/4/12 15:35:22", etc. The goal is to represent it in a way that a user, not a programmer, would want to read it. Chop off useless digits, pretend to be some other class — as long is it supports readability, it is an improvement.

Container’s __str__ uses contained objects’ __repr__

This seems surprising, doesn’t it? It is a little, but how readable would it be if it used their __str__?

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

Not very. Specifically, the strings in a container would find it way too easy to disturb its string representation. In the face of ambiguity, remember, Python resists the temptation to guess. If you want the above behavior when you’re printing a list, just

print("[" + ", ".join(l) + "]")

(you can probably also figure out what to do about dictionaries.

Summary

Implement __repr__ for any class you implement. This should be second nature. Implement __str__ if you think it would be useful to have a string version which errs on the side of readability.

Purpose of __repr__ method?

__repr__ should return a printable representation of the object, most likely one of the ways possible to create this object. See official documentation here. __repr__ is more for developers while __str__ is for end users.

A simple example:

>>> class Point:
... def __init__(self, x, y):
... self.x, self.y = x, y
... def __repr__(self):
... cls = self.__class__.__name__
... return f'{cls}(x={self.x!r}, y={self.y!r})'
>>> p = Point(1, 2)
>>> p
Point(x=1, y=2)

what is the significance of `__repr__` function over normal function

The __repr__ function is called by repr() internally. repr() is called when you are printing the object directly , and the class does not define a __str__() . From documentation -

object.__repr__(self)

Called by the repr() built-in function and by string conversions (reverse quotes) to compute the “official” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form <...some useful description...> should be returned. The return value must be a string object. If a class defines __repr__() but not __str__(), then __repr__() is also used when an “informal” string representation of instances of that class is required.

In your case for print_class() , you have to specifically call the method when printing the object. But in case of __repr__() , it gets internally called by print .

This is especially useful, when you are mixing different classes/types . For Example lets take a list which can have numbers and objects of your point class, now you want to print the elements of the list.

If you do not define the __repr__() or __str__() , you would have to first check the instance , whether its of type Point if so call print_class() , or if not directly print the number.

But when your class defines the __repr__() or __str__() , you can just directly call print on all the elements of the list, print statement would internally take care of printing the correct values.

Example , Lets assume a class which has print_class() method, but no __repr__() or __str__() , code -

>>> class CA:
... def __init__(self,x):
... self.x = x
... def print_class(self):
... return self.x
...
>>> l = [1,2,3,CA(4),CA(5)]
>>> for i in l:
... print(i)
...
1
2
3
<__main__.CA object at 0x00590F10>
<__main__.CA object at 0x005A5070>
SyntaxError: invalid syntax
>>> for i in l:
... if isinstance(i, CA):
... print(i.print_class())
... else:
... print(i)
...
1
2
3
4
5

As you can see, when we mix numbers and objects of type CA in the list, and then when we just did print(i) , it did not print what we wanted. For this to work correctly, we had to check the type of i and call the appropriate method (as done in second case).

Now lets assume a class that implements __repr__() instead of print_class() -

>>> class CA:
... def __init__(self,x):
... self.x = x
... def __repr__(self):
... return str(self.x)
...
>>>
>>> l = [1,2,3,CA(4),CA(5)]
>>> for i in l:
... print(i)
...
1
2
3
4
5

As you can see in second case, simply printing worked, since print internally calls __str__() first, and as that did not exist fell back to __repr__() .

And not just this, when we do str(list) , internally each list's element's __repr__() is called. Example -

First case (without __repr__() ) -

>>> str(l)
'[1, 2, 3, <__main__.CA object at 0x005AB3D0>, <__main__.CA object at 0x005AB410>]'

Second case (with __repr__() ) -

>>> str(l)
'[1, 2, 3, 4, 5]'

Also, in interactive interpreter, when you are directly using the object, it shows you the output of repr() function, Example -

>>> class CA:
... def __repr__(self):
... return "CA instance"
...
>>>
>>> c = CA()
>>> c
CA instance

How are __repr__ and __str__ implemented in print function

The explanation is not very good. I will try another one.

The difference between __repr__ and __str__ lies in the information value. The standard implementation is __repr__ and returns the class and the hash of the instance, which represents the memory address, as this is used by the interpreter for unique identification. It is the unique representation of an object's instance. However, this is not always helpful for the user. This is where __str__ comes into play.

Inheritance is an illustration of a tree structure. Every time you inherit from a class or type, you add another child node to the tree. The deeper you are in the tree, the more information may be available about the individual nodes.

Within my implementation of a tree you can see that the unique identification is given by the class, the module path and the content. However, the actual content of the node is more interesting for the user. However, this can vary depending on the use or depth within the tree.

Due to the amount of data that is collected in a sequence / iterable, it makes more sense to continuously output the __repr__ variant. In my implementation the __str__ output would make no sense, would change constantly and go beyond the scope if I wanted to output the entire tree. So with __str__ I only return the string of the real data. Remember, there may be a node that appears at a different location in the tree but contains the same content. These appear the same but are different.

Unfortunately I can't give you a better explanation. I hope it's not too weird and complicated.

Think about it.

I believe in you!

from abc import ABC
from typing import List

class BaseNode(ABC):

def __init__(self) -> None:
self._children = []
self._parent = None

def __len__(self) -> int:
return len(self._children)

def __repr__(self):
# python default implementation of __repr__
return f'<{self.__class__.__module__}.{self.__class__.__name__}' \
f' object at {self.__hash__()}>'

# python default implementation of __str__
__str__ = __repr__

def has_children(self) -> bool:
return len(self) > 0

def is_leaf(self) -> bool:
return not self.has_children()

def is_root(self) -> bool:
return self._parent is None

def add(self, child: 'BaseNode') -> 'BaseNode':
self._children.append(child)
child._parent = self
return self

def depth(self) -> int:
d,n = 0,self
while not n.is_root():
d,n = d+1,n._parent
return d

def descendants(self) -> List['Node']:
arr = []
if self.is_leaf(): return arr
else:
arr.extend(self._children)
for child in self._children:
arr.extend(child.descendants())
return arr

# abstract
def remove(self, child: 'BaseNode') -> 'BaseNode':
self._children.remove(child)
child._parent = None
return self


class RootNode(BaseNode):
pass

class Node(BaseNode):
def __init__(self, content):
super().__init__()
self._content = content

def __str__(self):
return self.content

@property
def content(self):
return self._content


def main():
node = RootNode()
node_a = Node('Node 1')
node_aa = Node('Node 1.1')
node_ab = Node('Node 1.2')
node_aba = Node('Node 1.2.1')
node_b = Node('Node 2')
node_ba = Node('Node 2.1')

node_ab.add(node_aba)
node_a.add(node_aa)
node_a.add(node_ab)
node.add(node_a)
node_b.add(node_ba)
node.add(node_b)

print(node)
print(str(node))
print(repr(node))
print(node.depth())
print(node.descendants())

print(node_aba)
print(str(node_aba))
print(repr(node_aba))
print(node_aba.depth())
print(node_aba.descendants())

if __name__ == '__main__':
main()
``

Why can __repr__ function use repr() in itself when defining a class?(Python)

    def __repr__(self):
if self.rest is not Link.empty:
rest_repr = ', ' + repr(self.rest)

Look at this piece of code, what do you notice?

Exactly: you are using repr(self.rest), which is equivalent to self.rest.__repr__().

In other words you aren't calling repr on an instance of Link, but just on an attribute of it. So you aren't calling Link.__repr__ into its body, don't worry.

Understanding difference between Double Quote and Single Quote with __repr__()

There is no semantic difference between ' and ". You can use ' if the string contains " and vice versa, and Python will do the same. If the string contains both, you have to escape some of them (or use triple quotes, """ or '''). (If both ' and " are possible, Python and many programmers seem to prefer ', though.)

>>> x = "string with ' quote"
>>> y = 'string with " quote'
>>> z = "string with ' and \" quote"
>>> x
"string with ' quote"
>>> y
'string with " quote'
>>> z
'string with \' and " quote'

About print, str and repr: print will print the given string with no additional quotes, while str will create a string from the given object (in this case, the string itself) and repr creates a "representation string" from the object (i.e. the string including a set of quotes). In a nutshell, the difference between str and repr should be that str is easy to understand for the user and repr is easy to understand for Python.

Also, if you enter any expression in the interactive shell, Python will automatically echo the repr of the result. This can be a bit confusing: In the interactive shell, when you do print(x), what you see is str(x); when you use str(x), what you see is repr(str(x)), and when you use repr(x), you see repr(repr(x)) (thus the double quotes).

>>> print("some string") # print string, no result to echo
some string
>>> str("some string") # create string, echo result
'some string'
>>> repr("some string") # create repr string, echo result
"'some string'"

Matlab repr function

Depending on exactly why you want to do this, your use case may be resolved with matlab.io.saveVariablesToScript

Here is the doc for it.

Hope that helps!



Related Topics



Leave a reply



Submit