DEV Community

Cover image for Python: the !r string format and the __repr__() and __str__() methods.
Be Hai Nguyen
Be Hai Nguyen

Posted on

5

Python: the !r string format and the __repr__() and __str__() methods.

The !r string format is a convenient one to use in certain cases. It is related closely to the __repr__() dunder method; and this method and the __str__() are often discussed together. In this post, we review __repr__() and __str__() methods and then the !r string format.

An usage example of the string format !r:

fmt_data = '{!r:^12} {!r:^15} {!r:^10}'
Enter fullscreen mode Exit fullscreen mode

On !r, PEP 3101 – Advanced String Formatting states:

!r - convert the value to a string using repr().

https://peps.python.org/pep-3101/#explicit-conversion-flag

repr() and str() official documentations can be found in the following links repr(object), class str(object=''), object.__repr_(self) and <a href="https://docs.python.org/3/reference/datamodel.html#object.str" title="object.str(self)" target="_blank">object.__str_(self)

Basically:

Let's illustrate this with an example:

class Person( object ):
    def __init__( self, given_name, surname ):
        self.__given_name = given_name
        self.__surname = surname

    def __repr__( self ):
        fmt = u"{}(given_name='{}', surname='{}')"

        return fmt.format( self.__class__.__name__, \
            self.__given_name, self.__surname )

    def __str__( self ):
        fmt = u"{}: Given Name: '{}', Surname: '{}')"

        return fmt.format( self.__class__.__name__, \
            self.__given_name, self.__surname )
Enter fullscreen mode Exit fullscreen mode

-- Please note, in case you wonder if I've copied this example from elsewhere... I have 😂, it is a very popular example used to illustrate this topic, I've also made some minor adjustments to it.

Let's see how it works:

person = Person( 'Văn Bé Hai', 'Nguyễn' ) 
# My full name, written in Vietnamese: Nguyễn Văn Bé Hai 😂

print( person.__str__() )
print( str( person ) )
print( '---' )
print( person.__repr__() )
print( repr( person ) )
Enter fullscreen mode Exit fullscreen mode

As expected, the output of object_instance.__str__() and str( object_instance ) are the same; and so do object_instance.__repr__() and repr( object_instance ).

Person: Given Name: 'Văn Bé Hai', Surname: 'Nguyễn')
Person: Given Name: 'Văn Bé Hai', Surname: 'Nguyễn')
---
Person(given_name='Văn Bé Hai', surname='Nguyễn')
Person(given_name='Văn Bé Hai', surname='Nguyễn')
Enter fullscreen mode Exit fullscreen mode

Continue on, let's see how person.__repr__() works with eval(expression[, globals[, locals]]):

repr_str = person.__repr__()
person1 = eval( repr_str )
print( str( person1 ) )
Enter fullscreen mode Exit fullscreen mode

And it does work as expected:

Person: Given Name: 'Văn Bé Hai', Surname: 'Nguyễn')
Enter fullscreen mode Exit fullscreen mode

Now, we try out !r string format with object instances person and person1:

print( '"person" instance reads: {!r}'.format(person) )
print( '"person1" instance reads: {!r}'.format(person1) )
Enter fullscreen mode Exit fullscreen mode

And we get:

"person" instance reads: Person(given_name='Văn Bé Hai', surname='Nguyễn')
"person1" instance reads: Person(given_name='Văn Bé Hai', surname='Nguyễn')
Enter fullscreen mode Exit fullscreen mode

-- The !r format does eventually call __repr__().

Back to class Person, we could get rid of the double single quote around the curly bracket pairs ( '{}' ) in the two variables fmt, and use {!r}:

class Person( object ):
    ...

    def __repr__( self ):
        # fmt = u"{}(given_name='{}', surname='{}')"
        fmt = u"{}(given_name={!r}, surname={!r})"
        ...     

    def __str__( self ):
        # fmt = u"{}: Given Name: '{}', Surname: '{}')"
        fmt = u"{}: Given Name: {!r}, Surname: {!r})"
        ...     
Enter fullscreen mode Exit fullscreen mode

Finally, let's look at the example listed in the beginning of this post: fmt_data = '{!r:^12} {!r:^15} {!r:^10}' -- please see this official document Format Specification Mini-Language for much more info. In a nutshell, ^ centres the string within the specified width, in this example, widths are 12, 15 and 10 respectively -- I have three ( 3 ) Boolean fields, and I would like to display them in tabular format, in the middle of three ( 3 ) headers with different lengths:

create_own = False
create_other = False 
view_own = True

fmt_header = '{:^12} {:^15} {:^10}'
fmt_data = '{!r:^12} {!r:^15} {!r:^10}'

print( fmt_header.format('Create Own', 'Create Other', 'View Own' ) )
print( fmt_data.format(create_own, create_other, view_own) )
Enter fullscreen mode Exit fullscreen mode

And the output looks like:

 Create Own   Create Other    View Own
   False          False         True
Enter fullscreen mode Exit fullscreen mode

This is what I mean in the beginning “The !r string format is a convenient one to use in certain cases.”

It seems Python offers a lot in term of string formatting. I find this information very useful. And I hope you do too. I certainly enjoy writing this post. Thank you for reading and stay safe as always.

Image of AssemblyAI tool

Transforming Interviews into Publishable Stories with AssemblyAI

Insightview is a modern web application that streamlines the interview workflow for journalists. By leveraging AssemblyAI's LeMUR and Universal-2 technology, it transforms raw interview recordings into structured, actionable content, dramatically reducing the time from recording to publication.

Key Features:
🎥 Audio/video file upload with real-time preview
🗣️ Advanced transcription with speaker identification
⭐ Automatic highlight extraction of key moments
✍️ AI-powered article draft generation
📤 Export interview's subtitles in VTT format

Read full post

Top comments (2)

Collapse
 
orangebirddrinkswater profile image
OrangeBirdDrinksWater

Your passage is really helpful.It helped me.

Collapse
 
behainguyen profile image
Be Hai Nguyen

Thank you.

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay