开发者

What is the purpose of __str__ and __repr__? [duplicate]

开发者 https://www.devze.com 2023-01-15 13:05 出处:网络
This question already has answers here: What is the difference between __str__ and __repr__? (28 answers)
This question already has answers here: What is the difference between __str__ and __repr__? (28 answers) Closed 2 years ago.

I really don't understand where are __str__ and __repr__ used in Python. I mean, I get that __str__ retur开发者_运维问答ns the string representation of an object. But why would I need that? In what use case scenario? Also, I read about the usage of __repr__

But what I don't understand is, where would I use them?


__repr__

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).

__str__

Called by the str() built-in function and by the print statement to compute the "informal" string representation of an object.

Use __str__ if you have a class, and you'll want an informative/informal output, whenever you use this object as part of string. E.g. you can define __str__ methods for Django models, which then gets rendered in the Django administration interface. Instead of something like <Model object> you'll get like first and last name of a person, the name and date of an event, etc.


__repr__ and __str__ are similar, in fact sometimes equal (Example from BaseSet class in sets.py from the standard library):

def __repr__(self):
    """Return string representation of a set.

    This looks like 'Set([<list of elements>])'.
    """
    return self._repr()

# __str__ is the same as __repr__
__str__ = __repr__


The one place where you use them both a lot is in an interactive session. If you print an object then its __str__ method will get called, whereas if you just use an object by itself then its __repr__ is shown:

>>> from decimal import Decimal
>>> a = Decimal(1.25)
>>> print(a)
1.25                  <---- this is from __str__
>>> a
Decimal('1.25')       <---- this is from __repr__

The __str__ is intended to be as human-readable as possible, whereas the __repr__ should aim to be something that could be used to recreate the object, although it often won't be exactly how it was created, as in this case.

It's also not unusual for both __str__ and __repr__ to return the same value (certainly for built-in types).


Building up and on the previous answers and showing some more examples. If used properly, the difference between str and repr is clear. In short repr should return a string that can be copy-pasted to rebuilt the exact state of the object, whereas str is useful for logging and observing debugging results. Here are some examples to see the different outputs for some known libraries.

Datetime

print repr(datetime.now())    #datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)
print str(datetime.now())     #2017-12-12 18:49:27.134452

The str is good to print into a log file, where as repr can be re-purposed if you want to run it directly or dump it as commands into a file.

x = datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)

Numpy

print repr(np.array([1,2,3,4,5])) #array([1, 2, 3, 4, 5])
print str(np.array([1,2,3,4,5]))  #[1 2 3 4 5]

in Numpy the repr is again directly consumable.

Custom Vector3 example

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

In this example, repr returns again a string that can be directly consumed/executed, whereas str is more useful as a debug output.

v = Vector3([1,2,3])
print str(v)     #x: 1, y: 2, z: 3
print repr(v)    #Vector3([1,2,3])

One thing to keep in mind, if str isn't defined but repr, str will automatically call repr. So, it's always good to at least define repr


Grasshopper, when in doubt go to the mountain and read the Ancient Texts. In them you will find that __repr__() should:

If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value.


Lets have a class without __str__ function.

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

emp1 = Employee('Ivan', 'Smith', 90000)

print(emp1)

When we print this instance of the class, emp1, this is what we get:

<__main__.Employee object at 0x7ff6fc0a0e48>

This is not very helpful, and certainly this is not what we want printed if we are using it to display (like in html)

So now, the same class, but with __str__ function:

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

    def __str__(self):
        return(f"The employee {self.first} {self.last} earns {self.pay}.")
        # you can edit this and use any attributes of the class

emp2 = Employee('John', 'Williams', 90000)

print(emp2)

Now instead of printing that there is an object, we get what we specified with return of __str__ function:

The employee John Williams earns 90000


str will be informal and readable format whereas repr will give official object representation.

class Complex:
    # Constructor
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag

    # "official" string representation of an object
    def __repr__(self):
        return 'Rational(%s, %s)' % (self.real, self.imag)

    # "informal" string representation of an object (readable)
    def __str__(self):
        return '%s + i%s' % (self.real, self.imag)

    t = Complex(10, 20)

    print (t)     # this is usual way we print the object
    print (str(t))  # this is str representation of object 
    print (repr(t))  # this is repr representation of object   

Answers : 

Rational(10, 20) # usual representation
10 + i20      # str representation
Rational(10, 20)  # repr representation


str and repr are both ways to represent. You can use them when you are writing a class.

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __repr__(self):
    return "{}/{}".format(self.n, self.d)

for example when I print a instance of it, it returns things.

print(Fraction(1, 2))

results in

1/2

while

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "{}/{}".format(self.n, self.d)
print(Fraction(1, 2))

also results in

1/2

But what if you write both of them, which one does python use?

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "str"
def __repr__(self):
    return "repr"

print(Fraction(None, None))

This results in

str

So python actually uses the str method not the repr method when both are written.


Suppose you have a class and wish to inspect an instance, you see the print doesn't give much useful information

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


p1 = Person("John", 36)
print(p1)  # <__main__.Animal object at 0x7f9060250410>

Now see a class with a str, it shows the instance information and with repr you even don't need the print. Nice no?

class Animal:
    def __init__(self, color, age, breed):
        self.color = color
        self.age = age
        self.breed = breed

    def __str__(self):
        return f"{self.color} {self.breed} of age {self.age}"

    def __repr__(self):
        return f"repr : {self.color} {self.breed} of age {self.age}"


a1 = Animal("Red", 36, "Dog")
a1  # repr : Red Dog of age 36
print(a1)  # Red Dog of age 36
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号