Какова цель __str__ и __repr__? [дубликат]

83

Я действительно не понимаю, где они __str__и __repr__используются в Python. Я имею в виду, я получаю, что __str__возвращает строковое представление объекта. Но зачем мне это нужно? В каком сценарии использования? Также я читал об использовании__repr__

Но я не понимаю, где бы я их использовал?

Даниэль
источник
4
Для всех, кто пришел с Ruby, tl; dr: __str__= to_sи __repr__= inspect.
Ajedi32
3
Отвечает ли это на ваш вопрос? Разница между __str__ и __repr__?
xiaoou wang

Ответы:

86

__repr__

Вызывается repr()встроенной функцией и преобразованием строк (обратными кавычками) для вычисления «официального» строкового представления объекта. Если это вообще возможно, это должно выглядеть как допустимое выражение Python, которое можно было бы использовать для воссоздания объекта с тем же значением (в соответствующей среде).

__str__

Вызывается str()встроенной функцией и оператором печати для вычисления «неформального» строкового представления объекта.

Используйте, __str__если у вас есть класс, и вам нужен информативный / неформальный вывод всякий раз, когда вы используете этот объект как часть строки. Например, вы можете определить __str__методы для моделей Django, которые затем будут отображаться в интерфейсе администрирования Django. Вместо чего-то вроде <Model object>вы получите имя и фамилию человека, имя и дату события и т. Д.


__repr__и __str__похожи, а иногда и равны (Пример из BaseSetкласса в sets.pyстандартной библиотеке):

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__
мику
источник
1
Благодаря! Это именно то, что я искал!
Даниэль
что делает `return self._repr ()`, когда я запускаю код и пытаюсь его понять, скажем, что __repr __ () принимает ровно один аргумент.
сияет
Итак, могу ли я использовать __repr__вместо __str__django?
Амит Трипати,
61

Единственное место, где вы часто используете их оба, - это интерактивный сеанс. Если вы напечатаете объект, __str__будет вызван его метод, тогда как если вы просто используете объект сам по себе, он __repr__будет показан:

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

Предполагается, __str__что код должен быть максимально удобочитаемым, тогда как__repr__ что объект объект должен быть чем-то, что можно использовать для воссоздания объекта, хотя часто это не совсем то, как он был создан, как в данном случае.

Также нет ничего необычного в том, что оба __str__и __repr__возвращают одно и то же значение (конечно, для встроенных типов).

Скотт Гриффитс
источник
Спасибо за пример, который
помог
17

Кузнечик, если сомневаешься, отправляйся на гору и прочитай Древние тексты . В них вы обнаружите, что __repr __ () должен:

Если это вообще возможно, это должно выглядеть как допустимое выражение Python, которое можно использовать для воссоздания объекта с тем же значением.

Питер Роуэлл
источник
6
-1, так как это даже не пытается ответить на фактический вопрос, а именно каковы варианты использования.
Скотт Гриффитс,
4
@Scott: Вы правы. Но опять же, в самом вопросе не было никакой попытки перейти к основным документам. Одно дело - задать вопрос, который показывает, что вы попытались ответить на него самостоятельно, но все еще немного запутались в некоторых его аспектах, и совсем другое дело - опубликовать такой вопрос. Просто введите его тему в качестве нового вопроса, чтобы увидеть, что 5 из 6 лучших предложенных тем SO ответили бы на его вопрос, но его это не беспокоило. Я не дал ему лёгкого ответа, но меня очень соблазнило.
Питер Роуэлл,
1
На самом деле он сказал, что читал __repr__, официальные документы на самом деле не отвечают на вопрос о том, почему вы бы его использовали, и то, что на вопрос дан ответ в другом месте, не является хорошей причиной для того, чтобы он не был ответил на SO (как правило, поиск в Google вернет вас сюда!) Если вы не думаете, что на вопрос стоит отвечать, вы просто не можете на него ответить, хотя в этом случае я согласен, что он уже очень хорошо освещен ТАК, и поэтому ссылка на дубликаты была бы подходящим ответом.
Скотт Гриффитс,
Собственно, вы ошибаетесь. В документации четко указано, почему вы должны его использовать, а именно: «Обычно это используется для отладки, поэтому важно, чтобы представление было насыщенным и однозначным». Я видел слишком много форумов (форумов?), Тонущих под тяжестью Help Vampires, и мне больно видеть, как это начинает происходить на SO. Что касается ссылки на другие очевидные ответы SO, в этом вся цель механизма предложений, который срабатывает, когда вы вводите строку темы, но он решил проигнорировать все предложения. QED и PDQ тоже.
Питер Роуэлл,
5
Что ж, в документации до сих пор не сказано, как использовать его для отладки, но я действительно не собирался спорить по этому поводу. Мы, по крайней мере, согласны с тем, что ваш ответ не касался вопроса, поэтому мой -1 все еще кажется мне оправданным. Если вопрос написан плохо / дублирован / тривиален, вы можете помочь улучшить вопрос, связать дубликаты или просто проголосовать за вопрос. Я думаю, что мое главное возражение здесь состоит в том, что ответы должны пытаться ответить на вопрос - есть другие механизмы для критики вопроса. Я заткнусь, так как думаю, у нас обоих есть дела поинтереснее.
Скотт Гриффитс,
14

Опираясь на предыдущие ответы и показывая еще несколько примеров. При правильном использовании разница между strи reprочевидна. Короче говоря, reprдолжен возвращать строку, которую можно скопировать и вставить для восстановления точного состояния объекта, тогда как strэто полезно для loggingиobserving отладки результатов. Вот несколько примеров, чтобы увидеть различные результаты для некоторых известных библиотек.

Дата и время

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

Это strудобно для печати в файл журнала, где reprего можно изменить, если вы хотите запустить его напрямую или выгрузить его в виде команд в файл.

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]

в Numpy repr это снова напрямую расходный материал.

Пользовательский пример Vector3

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)

В этом примере reprснова возвращает строку, которую можно напрямую использовать / выполнить, тогда как strона более полезна в качестве вывода отладки.

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

Одна вещь , чтобы иметь в виду, если strне определено , но repr, strбудет автоматически вызывать repr. Так что всегда хорошо хотя бы определитьrepr

user1767754
источник
5

Давайте иметь класс без __str__функции.

class Employee:

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

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

print(emp1)

Когда мы печатаем этот экземпляр класса, emp1мы получаем следующее:

<__main__.Employee object at 0x7ff6fc0a0e48>

Это не очень полезно, и, конечно же, это не то, что мы хотим напечатать, если мы используем его для отображения (например, в html)

Итак, тот же класс, но с __str__функцией:

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)

Теперь вместо того, чтобы печатать, что есть объект, мы получаем то, что указали при возврате __str__функции:

The employee John Williams earns 90000

Зорана
источник
3

strбудет неформальным и читаемым форматом, тогда как reprдаст официальное представление объекта.

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
Вишваджит Патхак
источник
1

str и repr - оба способа представления. Вы можете использовать их при написании класса.

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

например, когда я печатаю его экземпляр, он возвращает вещи.

print(Fraction(1, 2))

приводит к

1/2

в то время как

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

также приводит к

1/2

Но что, если вы напишете их оба, какой из них использует Python?

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

Это приводит к

str

Итак, python фактически использует метод str, а не метод repr, когда оба написаны.

KingWitherBrine
источник
0

Предположим, у вас есть класс и вы хотите проверить экземпляр, вы видите, что печать не дает много полезной информации.

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


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

Теперь посмотрите на класс с str , он показывает информацию об экземпляре, а с repr вам даже не нужна печать. Хорошо, нет?

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
xiaoou wang
источник