Pertanyaan Perbedaan antara __str__ dan __repr__?


Apa perbedaan antara __str__ dan __repr__ di Python?


2107
2017-09-17 04:27


asal


Jawaban:


Alex diringkas dengan baik tetapi, yang mengejutkan, terlalu ringkas.

Pertama, izinkan saya mengulangi poin utama dalam Pos Alex:

  • Penerapan default tidak berguna (sulit memikirkan yang tidak mungkin, tapi ya)
  • __repr__ tujuannya adalah menjadi tidak ambigu
  • __str__ tujuannya adalah untuk dapat dibaca
  • Penampung __str__ menggunakan objek yang terkandung __repr__

Implementasi default tidak berguna

Ini sebagian besar merupakan kejutan karena default Python cenderung cukup bermanfaat. Namun, dalam hal ini, memiliki default untuk __repr__ yang akan bertindak seperti:

return "%s(%r)" % (self.__class__, self.__dict__)

akan terlalu berbahaya (misalnya, terlalu mudah untuk masuk ke dalam rekursi tanpa batas jika objek saling mereferensikan). Jadi polisi Python keluar. Perhatikan bahwa ada satu default yang benar: jika __repr__ didefinisikan, dan __str__ tidak, objek akan berperilaku seolah-olah __str__=__repr__.

Ini berarti, dalam istilah sederhana: hampir setiap objek yang Anda laksanakan harus memiliki fungsional __repr__ yang dapat digunakan untuk memahami objek. Menerapkan __str__ adalah opsional: lakukan itu jika Anda memerlukan fungsionalitas "cantik cetak" (misalnya, digunakan oleh generator laporan).

Tujuan dari __repr__ adalah menjadi tidak ambigu

Biarkan saya keluar dan mengatakannya - Saya tidak percaya pada debugger. Saya tidak benar-benar tahu cara menggunakan debugger apa pun, dan tidak pernah menggunakannya secara serius. Selanjutnya, saya percaya bahwa kesalahan besar dalam debugger adalah sifat dasar mereka - kebanyakan kegagalan yang saya debug terjadi sejak lama, di galaksi yang sangat jauh. Ini berarti bahwa saya percaya, dengan semangat religius, dalam penebangan. Penebangan kayu adalah sumber kehidupan dari sistem server yang aman dan lupakan api. Python membuatnya mudah untuk masuk: dengan mungkin beberapa pembungkus khusus proyek, yang Anda butuhkan hanyalah a

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

Tetapi Anda harus melakukan langkah terakhir - pastikan setiap objek yang Anda laksanakan memiliki repr yang berguna, sehingga kode seperti itu dapat berfungsi. Inilah sebabnya mengapa hal “eval” muncul: jika Anda memiliki cukup informasi eval(repr(c))==c, itu berarti Anda tahu segalanya yang perlu diketahui c. Jika itu cukup mudah, setidaknya dengan cara yang tidak jelas, lakukan saja. Jika tidak, pastikan Anda memiliki cukup informasi c bagaimanapun. Saya biasanya menggunakan format seperti eval: "MyClass(this=%r,that=%r)" % (self.this,self.that). Ini tidak berarti bahwa Anda benar-benar dapat membangun MyClass, atau bahwa mereka adalah argumen konstruktor yang tepat - tetapi ini adalah bentuk yang berguna untuk menyatakan "ini adalah semua yang perlu Anda ketahui tentang hal ini".

Catatan: Saya menggunakan %r di atas, bukan %s. Anda selalu ingin menggunakannya repr() [atau %r memformat karakter, ekuivalen] di dalam __repr__ implementasi, atau Anda mengalahkan tujuan dari repr. Anda ingin dapat membedakan MyClass(3) dan MyClass("3").

Tujuan dari __str__ harus bisa dibaca

Secara khusus, itu tidak dimaksudkan untuk menjadi ambigu - perhatikan itu str(3)==str("3"). Demikian juga, jika Anda menerapkan abstraksi IP, memiliki str itu terlihat seperti 192.168.1.1 baik-baik saja. Ketika menerapkan abstraksi tanggal / waktu, str bisa menjadi "2010/4/12 15:35:22", dll. Tujuannya adalah untuk merepresentasikannya dengan cara yang pengguna, bukan programmer, ingin membacanya. Potong angka yang tidak berguna, berpura-pura menjadi beberapa kelas lain - selama mendukung keterbacaan, itu adalah perbaikan.

Penampung __str__ menggunakan objek yang terkandung __repr__

Ini sepertinya mengejutkan, bukan? Ini sedikit, tetapi seberapa mudah dibaca

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

menjadi? Tidak terlalu. Secara khusus, string dalam wadah akan merasa terlalu mudah untuk mengganggu representasi string-nya. Dalam menghadapi ambiguitas, ingat, Python menolak godaan untuk menebak. Jika Anda menginginkan perilaku di atas saat Anda hanya mencetak daftar

print "[" + ", ".join(l) + "]"

(Anda mungkin juga bisa mencari tahu apa yang harus dilakukan tentang kamus.

Ringkasan

Melaksanakan __repr__ untuk kelas apa pun yang Anda terapkan. Ini harus menjadi sifat kedua. Melaksanakan __str__ jika Anda berpikir akan berguna untuk memiliki versi string yang keliru pada sisi keterbacaan lebih banyak dalam mendukung lebih banyak ambiguitas.


2171
2018-04-13 00:56



Aturan saya: __repr__ adalah untuk para pengembang, __str__ untuk pelanggan.


369
2017-09-17 11:35



Kecuali Anda secara khusus bertindak untuk memastikan sebaliknya, sebagian besar kelas tidak memiliki hasil yang bermanfaat untuk:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

Seperti yang Anda lihat - tidak ada perbedaan, dan tidak ada info di luar kelas dan objek id. Jika Anda hanya mengganti salah satu dari dua ...:

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

seperti yang Anda lihat, jika Anda menimpa __repr__, itu juga digunakan untuk __str__, tapi tidak sebaliknya.

Informasi penting lainnya yang perlu diketahui: __str__ pada wadah built-on menggunakan __repr__, Bukan __str__, untuk barang-barang yang dikandungnya. Dan, terlepas dari kata-kata pada subjek yang ditemukan di dokumen-dokumen biasa, hampir tidak ada orang yang membuat __repr__ benda menjadi string itu eval dapat digunakan untuk membangun objek yang sama (itu terlalu sulit, dan tidak tahu bagaimana modul yang relevan sebenarnya diimpor membuatnya benar-benar tidak mungkin).

Jadi, saran saya: fokus pada pembuatan __str__ cukup terbaca manusia, dan __repr__ sesederhana mungkin, bahkan jika itu mengganggu tujuan pembuatan yang kabur __repr__Nilai yang dikembalikan dapat diterima sebagai masukan __eval__!


319
2017-09-17 04:49



__repr__: representasi objek python biasanya eval akan mengubahnya kembali ke objek itu

__str__: adalah apa pun yang Anda pikirkan adalah objek dalam bentuk teks

misalnya

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True

143
2017-09-17 04:35



Singkatnya, tujuan dari __repr__ adalah tidak ambigu dan __str__ harus menjadi   dapat dibaca.

Ini contoh yang bagus:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

Baca dokumentasi ini untuk repr:

repr(object)

Kembalikan string yang berisi representasi objek yang dapat dicetak. Ini adalah nilai yang sama yang dihasilkan oleh konversi (sebaliknya   tanda kutip). Terkadang berguna untuk dapat mengakses operasi ini sebagai   fungsi biasa. Untuk banyak jenis, fungsi ini berusaha   untuk mengembalikan string yang akan menghasilkan objek dengan nilai yang sama saat   diteruskan ke eval(), jika representasi adalah string tertutup   kurung sudut yang berisi nama jenis objek   bersama dengan informasi tambahan sering termasuk nama dan   alamat objek. Kelas dapat mengontrol apa yang dikembalikan fungsi ini   untuk contohnya dengan mendefinisikan a __repr__() metode.

Berikut ini dokumentasi untuk str:

str(object='')

Kembalikan string yang berisi cetakan yang bagus   representasi suatu objek. Untuk string, ini mengembalikan string   diri. Perbedaannya dengan repr(object)Apakah itu str(object) tidak   selalu berusaha mengembalikan string yang dapat diterima eval(); -nya   tujuannya adalah mengembalikan string yang dapat dicetak. Jika tidak ada argumen yang diberikan, kembalikan   string kosong, ''.


114
2017-10-25 18:38



Apa perbedaan antara __str__ dan __repr__ dengan Python?

__str__ (dibaca sebagai "dunder (double-underscore) string") dan __repr__ (dibaca sebagai "dunder-repper" (untuk "representasi")) keduanya adalah metode khusus yang mengembalikan string berdasarkan keadaan objek.

__repr__ menyediakan perilaku pencadangan jika __str__ hilang.

Jadi yang pertama harus menulis a __repr__ yang memungkinkan Anda untuk mengaktifkan kembali objek yang setara dari string yang dibawanya, mis. menggunakan eval atau dengan mengetikkannya dalam karakter-untuk-karakter dalam shell Python.

Setiap saat kemudian, seseorang dapat menulis a __str__ untuk representasi string yang dapat dibaca pengguna dari instance, ketika seseorang meyakini itu perlu.

__str__

Jika Anda mencetak objek, atau menyebarkannya format, str.format, atau str, lalu jika a __str__ metode didefinisikan, metode itu akan dipanggil, jika tidak, __repr__ akan digunakan.

__repr__

Itu __repr__ metode dipanggil oleh fungsi builtin repr dan apa yang digemakan pada shell python Anda ketika mengevaluasi ekspresi yang mengembalikan objek.

Karena ini menyediakan cadangan untuk __str__, jika Anda hanya bisa menulis satu, mulailah dengan __repr__

Inilah bantuan builtin repr:

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

Artinya, untuk sebagian besar objek, jika Anda mengetikkan apa yang dicetak oleh repr, Anda harus dapat membuat objek yang setara. Tapi ini bukan implementasi standar.

Implementasi Default dari __repr__

Objek default __repr__ aku s (C sumber Python) sesuatu seperti:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

Itu berarti secara default Anda akan mencetak modul objeknya dari, nama kelas, dan representasi heksadesimal dari lokasinya di memori - misalnya:

<__main__.Foo object at 0x7f80665abdd0>

Informasi ini tidak sangat berguna, tetapi tidak ada cara untuk mendapatkan bagaimana seseorang dapat secara akurat membuat representasi kanonikal dari suatu contoh yang diberikan, dan itu lebih baik daripada tidak sama sekali, setidaknya memberi tahu kita bagaimana kita dapat mengidentifikasi secara unik dalam memori.

Bagaimana bisa __repr__ menjadi berguna?

Mari kita lihat bagaimana bergunanya, menggunakan shell Python dan datetime objek. Pertama kita perlu mengimpor datetime modul:

import datetime

Jika kita memanggil datetime.now di shell, kita akan melihat semua yang kita butuhkan untuk membuat ulang objek datetime yang setara. Ini dibuat oleh datetime __repr__:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

Jika kita mencetak objek datetime, kita melihat format yang dapat dibaca manusia (pada kenyataannya, ISO). Ini diimplementasikan oleh datetime itu __str__:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

Ini adalah masalah sederhana untuk membuat ulang objek yang hilang karena kami tidak menugaskannya ke variabel dengan menyalin dan menempel dari __repr__ output, dan kemudian mencetaknya, dan kita mendapatkannya dalam output yang dapat dibaca manusia yang sama dengan objek lainnya:

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

Bagaimana cara menerapkannya?

Ketika Anda sedang mengembangkan, Anda akan ingin dapat mereproduksi objek dalam keadaan yang sama, jika memungkinkan. Ini, misalnya, adalah bagaimana mendefinisikan objek datetime __repr__ (Sumber Python). Ini cukup rumit, karena semua atribut yang dibutuhkan untuk mereproduksi objek seperti itu:

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day, # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = ", ".join(map(str, L))
    s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    return s

Jika Anda ingin objek Anda memiliki representasi yang dapat dibaca manusia, Anda dapat menerapkan __str__ berikutnya. Begini cara objek datetime (Sumber Python) mengimplementasikan __str__, yang mudah dilakukan karena sudah memiliki fungsi untuk menampilkannya dalam format ISO:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

Set __repr__ = __str__?

Ini adalah kritik dari jawaban lain di sini yang menyarankan pengaturan __repr__ = __str__.

Pengaturan __repr__ = __str__ itu konyol - __repr__ adalah fallback untuk __str__ dan a __repr__, ditulis untuk penggunaan pengembang dalam debugging, harus ditulis sebelum Anda menulis __str__.

Anda membutuhkan sebuah __str__ hanya ketika Anda membutuhkan representasi tekstual objek.

Kesimpulan

Menetapkan __repr__ untuk objek yang Anda tulis sehingga Anda dan pengembang lain memiliki contoh yang dapat direproduksi saat menggunakannya saat Anda mengembangkannya. Menetapkan __str__ ketika Anda membutuhkan representasi string yang dapat dibaca manusia itu.


84
2018-01-25 02:01



Terlepas dari semua jawaban yang diberikan, saya ingin menambahkan beberapa poin: -

1) __repr__() dipanggil ketika Anda hanya menulis nama objek di konsol python interaktif dan tekan enter.

2) __str__() dipanggil ketika Anda menggunakan objek dengan pernyataan cetak.

3) Dalam hal, jika __str__ hilang, lalu cetak dan fungsi apa pun yang digunakan str() meminta __repr__() objek.

4) __str__() kontainer, ketika dipanggil akan dieksekusi __repr__() metode elemen yang terkandung.

5) str() disebut di dalam __str__() dapat berpotensi rekursi tanpa case dasar, dan kesalahan pada kedalaman rekursi maksimum.

6) __repr__() dapat menelepon repr() yang akan mencoba untuk menghindari rekursi tak terbatas secara otomatis, mengganti objek yang sudah diwakili dengan ....


12
2017-09-08 03:27



Sejujurnya, eval(repr(obj)) tidak pernah digunakan. Jika Anda menemukan diri Anda menggunakannya, Anda harus berhenti, karena eval berbahaya, dan string adalah cara yang sangat tidak efisien untuk membuat serial objek Anda (gunakan pickle sebagai gantinya).

Oleh karena itu, saya akan merekomendasikan pengaturan __repr__ = __str__. Alasannya adalah itu str(list) panggilan repr pada elemen (Saya menganggap ini sebagai salah satu kelemahan desain terbesar Python yang tidak ditangani oleh Python 3). Sebenarnya repr mungkin tidak akan sangat membantu sebagai output dari print [your, objects].

Untuk memenuhi syarat ini, dalam pengalaman saya, kasus penggunaan yang paling berguna repr fungsi adalah meletakkan string di dalam string lain (menggunakan format string). Dengan cara ini, Anda tidak perlu khawatir tentang tanda kutip atau apa pun. Tetapi perhatikan bahwa tidak ada eval terjadi di sini.


11
2017-11-15 10:39



Untuk membuatnya lebih sederhana:

__str__ digunakan untuk menunjukkan representasi string objek Anda untuk dibaca dengan mudah oleh orang lain.

__repr__ digunakan untuk menunjukkan representasi string itu obyek.

Katakanlah saya ingin membuat Fraction kelas di mana representasi string dari pecahan adalah '(1/2)' dan objek (Kelas pecahan) harus direpresentasikan sebagai 'Fraksi (1,2)'

Jadi kita bisa membuat kelas Fraksi sederhana:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)

10
2018-01-12 02:53



Di halaman 358 buku Python scripting untuk ilmu komputasi oleh Hans Petter Langtangen, dengan jelas menyatakan hal itu

  • Itu __repr__bertujuan representasi string lengkap dari objek;
  • Itu __str__ adalah mengembalikan string yang bagus untuk dicetak.

Jadi, saya lebih suka memahami mereka sebagai

  • repr = mereproduksi
  • str = string (representasi)

dari sudut pandang pengguna meskipun ini adalah kesalahpahaman yang saya buat ketika belajar python.

Contoh kecil tapi bagus juga diberikan pada halaman yang sama seperti berikut:

Contoh

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'

10
2018-05-21 16:34



Dari http://pyref.infogami.com/__str__ oleh effbot:

__str__ msgstr "hitung representasi string" informal "dari suatu objek. Ini berbeda dari __repr__ karena itu tidak harus menjadi ekspresi Python yang valid: representasi yang lebih nyaman atau ringkas dapat digunakan sebagai gantinya. "


9
2017-09-17 04:28