Python-Detailed explanation of __str__, __repr__ and __format__

This article originated from a personal public account : TechFlow , original is not easy, seek attention


Today is the 10th article on the topic of Python . Let ’s talk about the classes in Python.

Print example

Let's start with the simplest printout of classes and objects. Printing an example is a very humble application, but it is very important in actual programming. The reason is also very simple, because when we debug, we often want to see if the content in a certain class meets our expectations. But if we print the output directly, we will only get an address.

Let's look at an example:

class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y


if __name__ == "__main__":
    p = point(3, 4)
    print(p)

In this code, we define a simple class with two elements, x and y, but if we run it directly, the screen will output such a result:

<__main__.point object at 0x10a18c210>

This is some relevant information of this instance when the interpreter is executed, but it has little reference significance for us. What we want is the specific value in this instance, not the address in a memory.

To achieve this function, we have many methods, let's take a look at them one by one.

__str__ method

The __str__ method should be familiar to everyone. It is similar to the toString method in Java, and can return the result after the instance is converted into a string according to our needs.

For example, we can overload this method in the class, and we can output the result according to our needs:

class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return 'x: %s, y: %s' % (self.x, self.y)

When we run it, the result will be:

x: 3, y: 4

__str__ and __init__, __len__ are many functions that are special functions in Python . When we create a class, the system will create many such special functions implicitly. We can overload some of them as needed to complete the functions we want. For example, if we are writing a binary tree class, we can also recursively traverse all the nodes in the __str__ function to print out the complete tree.

__repr__ method

You may have heard of the __repr__ function, which can also realize the function of customizing the output according to our needs. For example, if we change the above code to the function name, we can also get the same result.

class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'x: %s, y: %s' % (self.x, self.y)

If we run it, we will also get:

x: 3, y: 4

Why is this, is __repr__ and __str__ the same? If they are the same, why should Python designers keep two identical functions? Why not remove one of them?

Before analyzing the reasons, let's do an experiment first. If both of our functions are overloaded, when we output, which one is the program executing? In order to make a distinction, we slightly modified the format of the output in repr.

class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return 'x: %s, y: %s' % (self.x, self.y)

    def __repr__(self):
        return '<point x: %s, y: %s>' % (self.x, self.y)

After we run it, we will find that the output is still:

x: 3, y: 4

Don't worry about drawing conclusions first, let's copy this code into jupyter notebook . This time, instead of printing out, we will output the interactive results through the interactive box that comes with jupyter. Let's take a look:

Strange, how did the result become the result of __repr__?

In fact, this is the difference between the two . If you simply understand, these two functions will convert an instance into a string. But the difference is that the two use scenarios are different, and __str__ is more focused on display. So when we print output to the user or use the str function for type conversion , Python will first call the __str__ function by default. The __repr__ is more focused on the report of this instance. In addition to the content of the instance, we often attach information related to its class, because these contents are for developers . So when we output in the interactive window, it will call __repr__ first.

In theory, for a qualified __repr__ function to be able to do:

eval(repr(obj)) == obj

In other words, we can restore the instance itself after executing the content output by __repr__. Of course, in some scenarios, this is very difficult to achieve, so we fall back to the second place, and ensure that there are enough output classes and objects in __repr__ Information, it is convenient for developers to debug and use.

In addition, repr is the abbreviation of report, so it has a report meaning in it, and str is just converted into a string. There is still a certain difference between the two.

format

In addition to the above two, the most commonly used output function in Python is format .

The simpler usage is to represent variables by {}, and then enter them in order:

In addition, we can further specify the variable names in curly brackets to further increase readability:

The function of format is much more than that. It also supports many parameters, similar to printf in C language, which can achieve a variety of output through different parameters. For example, control the number of digits reserved after the decimal point, or convert it into a percentage, scientific notation, left-right alignment and other functions. I wo n’t list them one by one, just check them when you need them.

We can of course use format to recreate the logic in __repr__ and __str__, but this does not reflect its power. Because in Python, the special function __format__ is also provided for the class. By rewriting __format__ and using format, we can achieve even more powerful functions.

format joint __format__

We can overload the __format__ function in the class, so that we can call the object directly through the format function externally and output the result we want.

Let's look at the code:

class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return 'x: %s, y: %s' % (self.x, self.y)

    def __format__(self, code):
        return 'x: {x}, y: {y}'.format(x = self.x, y = self.y)

We changed the __repr__ to __format__ just now, but we need to pay attention to one detail. We added a parameter code . This is because the format supports the function of configuring the processing logic through parameters, so we must be at the interface Add one more parameter. After adding it, we can directly call format§.

It is not over yet. In some scenes, we may have multiple output formats for the same object . For example, in some scenes we may want to output (x, y), sometimes we want to output x: 3, y: 4, and in some scenes, we want to output <x, y>.

We aim at so many scenarios, it would be very troublesome to implement different interfaces. At this time, using this parameter in __format__ can greatly simplify this process. Let's look at the code:

formats = {
    'normal': 'x: {p.x}, y: {p.y}',
    'point' : '({p.x}, {p.y})',
    'prot': '<{p.x}, {p.y}>'
}

class point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return 'x: %s, y: %s' % (self.x, self.y)

    def __format__(self, code):
        return formats[code].format(p=self)

We can use parameters to control which format we use to format the object when we call it :

That is to say, by overloading the __format__ method, we have made the originally fixed formatting logic configurable . This greatly increases the flexibility of our use process, this flexibility can greatly simplify and concise our code in some problem scenarios. For the language of Python, I personally feel that implementing functions is only a small part of it. Writing code concisely and beautifully is the main part. This is why many people say that Python is easy to learn and difficult to learn .

Today's article is just that. If you feel something rewarded, please follow or repost it. Your effort is very important to me.

Insert picture description here

Published 117 original articles · Like 61 · Visits 10,000+

Guess you like

Origin blog.csdn.net/TechFlow/article/details/105520075