Яке призначення __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()вбудованою функцією та оператором print для обчислення "неформального" рядкового представлення об'єкта.

Використовуйте, __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__повернення одного і того ж значення (звичайно, для вбудованих типів).


Дякую за приклад, дав мені краще зрозуміти, де це використовується за замовчуванням
JayRizzo

17

Коник, коли сумніваєтеся, вирушайте на гору і читайте Стародавні тексти . У них ви знайдете, що __repr __ () повинен:

Якщо це можливо, це повинно виглядати як дійсний вираз Python, який можна використовувати для відтворення об’єкта з однаковим значенням.


6
-1, оскільки це навіть не намагається відповісти на фактичне питання, яким є випадки використання.
Скотт Гріффітс,

4
@Scott: Ви маєте рацію. Але знову ж таки фактичне запитання не показало абсолютно жодної спроби перейти до основних документів спочатку. Одна справа - задати питання, яке свідчить про те, що ви зробили спробу відповісти на нього самі, але все ще трохи розгублені щодо якогось його аспекту, а інша справа - опублікувати таке запитання. Просто введення в його рядок теми, як нове запитання, показує, що 5 із 6 найкращих запропонованих потоків SO відповіли б на його запитання, але його не можна було турбувати. Я не зовсім дав йому відповідь lmgtfy, але мене дуже спокусило.
Пітер Роуелл

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


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, коли обидва написані.


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 , він показує інформацію про екземпляр, а з перевиданням вам навіть не потрібен друк. Приємно ні?

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.