Apa perbedaan antara __str__
dan __repr__
dalam Python?
sumber
Alex merangkum dengan baik tetapi, yang mengejutkan, terlalu ringkas.
Pertama, izinkan saya mengulangi poin utama dalam posting Alex :
__repr__
tujuannya adalah untuk tidak ambigu__str__
tujuannya adalah agar dapat dibaca__str__
menggunakan terkandung benda__repr__
Implementasi default tidak berguna
Ini sebagian besar mengejutkan karena standar Python cenderung cukup berguna. Namun, dalam hal ini, memiliki default __repr__
yang akan bertindak seperti:
return "%s(%r)" % (self.__class__, self.__dict__)
akan terlalu berbahaya (misalnya, terlalu mudah untuk masuk ke rekursi tak terbatas jika benda saling referensi). Jadi Python keluar. Perhatikan bahwa ada satu default yang benar: jika __repr__
didefinisikan, dan __str__
tidak, objek akan berperilaku seolah-olah __str__=__repr__
.
Ini berarti, secara sederhana: hampir setiap objek yang Anda implementasikan harus memiliki fungsional __repr__
yang dapat digunakan untuk memahami objek. Penerapan __str__
adalah opsional: lakukan itu jika Anda memerlukan fungsionalitas "cetak cantik" (misalnya, digunakan oleh pembuat laporan).
Tujuannya __repr__
adalah untuk tidak ambigu
Biarkan saya keluar dan mengatakannya - saya tidak percaya pada para penentang. Saya tidak benar-benar tahu cara menggunakan debugger apa pun, dan belum pernah menggunakannya secara serius. Lebih jauh lagi, 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 benar-benar percaya, dengan semangat keagamaan, dalam penebangan. Logging adalah sumber kehidupan dari sistem server fire-and-forget yang layak. Python membuatnya mudah untuk login: 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 implementasikan memiliki repr yang berguna, jadi kode seperti itu bisa berfungsi. Inilah sebabnya mengapa "eval" muncul: jika Anda memiliki informasi yang cukup eval(repr(c))==c
, itu berarti Anda tahu semua yang perlu diketahui c
. Jika itu cukup mudah, setidaknya dengan cara yang kabur, lakukanlah. Jika tidak, pastikan Anda memiliki informasi yang cukup tentang hal c
itu. Saya biasanya menggunakan format seperti eval:"MyClass(this=%r,that=%r)" % (self.this,self.that)
. Itu tidak berarti bahwa Anda benar-benar dapat membangun MyClass, atau bahwa itu adalah argumen konstruktor yang tepat - tetapi itu adalah bentuk yang berguna untuk menyatakan "ini adalah semua yang perlu Anda ketahui tentang instance ini".
Catatan: Saya menggunakan di %r
atas, tidak %s
. Anda selalu ingin menggunakan repr()
[atau %r
memformat karakter, setara] di dalam __repr__
implementasi, atau Anda mengalahkan tujuan repr. Anda ingin dapat membedakan MyClass(3)
dan MyClass("3")
.
Tujuannya __str__
agar dapat dibaca
Secara khusus, ini tidak dimaksudkan untuk tidak 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 dapat berupa "2010/4/12 15:35:22", dll. Tujuannya adalah untuk mewakilinya dengan cara yang ingin dibaca oleh pengguna, bukan programmer. Memotong angka yang tidak berguna, berpura-pura menjadi kelas lain - selama itu mendukung keterbacaan, itu adalah peningkatan.
Wadah ini __str__
menggunakan terkandung benda__repr__
Ini sepertinya mengejutkan, bukan? Ini sedikit, tetapi seberapa mudah dibaca jika digunakan __str__
?
[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
Tidak terlalu. Secara khusus, string dalam wadah akan merasa terlalu mudah untuk mengganggu representasi string-nya. Dalam menghadapi ambiguitas, ingatlah, Python menolak godaan untuk menebak. Jika Anda ingin perilaku di atas saat Anda mencetak daftar, cukup
print "[" + ", ".join(l) + "]"
(Anda mungkin juga bisa mencari tahu apa yang harus dilakukan tentang kamus.
Ringkasan
Terapkan __repr__
untuk kelas yang Anda laksanakan. Ini harus menjadi sifat kedua. Terapkan __str__
jika Anda pikir akan bermanfaat untuk memiliki versi string yang salah di sisi keterbacaan.
__repr__
itulah yang saya butuhkan untuk debugging. Terima kasih untuk bantuannya.Aturan praktis saya:
__repr__
untuk pengembang,__str__
untuk pelanggan.sumber
__str__
sehingga pengembang normal memiliki objek yang dapat dibaca. Di sisi lain,__repr__
adalah untuk para pengembang SDK sendiri.Kecuali Anda secara khusus bertindak untuk memastikan sebaliknya, sebagian besar kelas tidak memiliki hasil yang bermanfaat untuk:
Seperti yang Anda lihat - tidak ada perbedaan, dan tidak ada info di luar kelas dan objek
id
. Jika Anda hanya mengganti satu dari dua ...:seperti yang Anda lihat, jika Anda menimpa
__repr__
, itu JUGA digunakan untuk__str__
, tetapi tidak sebaliknya.Informasi penting lainnya yang perlu diketahui:
__str__
pada wadah bawaan menggunakan__repr__
, BUKAN__str__
, untuk item yang dikandungnya. Dan, terlepas dari kata-kata pada subjek yang ditemukan dalam dokumen biasa, hampir tidak ada orang yang mengganggu membuat__repr__
objek menjadi string yangeval
dapat digunakan untuk membangun objek yang sama (itu terlalu sulit, DAN tidak tahu bagaimana modul yang relevan sebenarnya diimpor membuatnya benar-benar tidak mungkin keluar).Jadi, saran saya: fokuslah untuk membuat yang
__str__
dapat dibaca manusia, dan__repr__
sejelas mungkin, bahkan jika itu mengganggu tujuan tidak jelas yang tidak dapat dicapai untuk membuat__repr__
nilai yang dikembalikan dapat diterima sebagai masukan untuk__eval__
!sumber
eval(repr(foo))
mengevaluasi ke objek yang sama denganfoo
. Anda benar bahwa itu tidak akan berfungsi di luar kasus pengujian saya karena saya tidak tahu bagaimana modul diimpor, tetapi ini setidaknya memastikan bahwa itu berfungsi dalam beberapa konteks yang dapat diprediksi. Saya pikir ini cara yang baik untuk mengevaluasi jika hasilnya__repr__
cukup eksplisit. Melakukan ini dalam unit test juga membantu memastikan bahwa__repr__
perubahan berikut mengikuti kelas.eval(repr(spam)) == spam
(setidaknya dalam konteks yang tepat), ataueval(repr(spam))
memunculkan aSyntaxError
. Dengan begitu Anda menghindari kebingungan. (Dan itu hampir benar untuk builtin dan sebagian besar stdlib, kecuali untuk, misalnya, daftar rekursif, di manaa=[]; a.append(a); print(eval(repr(a)))
memberi Anda[[Ellipses]]
...) Tentu saja saya tidak melakukan itu untuk benar-benar digunakaneval(repr(spam))
, kecuali sebagai pemeriksaan kewarasan dalam unit test ... tapi saya lakukan terkadang salin dan tempelrepr(spam)
ke sesi interaktif.__str__
untuk setiap elemen, bukan__repr__
? Tampak jelas salah bagi saya, karena saya menerapkan yang dapat dibaca__str__
di objek saya dan ketika itu adalah bagian dari daftar saya melihat yang lebih buruk__repr__
sebagai gantinya.eval(repr(x))
gagal bahkan untuk tipe bawaan:class A(str, Enum): X = 'x'
akan meningkatkan SyntaxErroreval(repr(A.X))
. Sedih, tapi bisa dimengerti. BTW,eval(str(A.X))
sebenarnya berfungsi, tetapi tentu saja hanya jikaclass A
dalam ruang lingkup - jadi mungkin tidak terlalu berguna.str
elemen penggunaan wadahrepr
karena[1, 2, 3]
! =["1", "2, 3"]
.__repr__
: representasi objek python biasanya eval akan mengubahnya kembali ke objek itu__str__
: adalah apa pun yang Anda pikirkan adalah objek itu dalam bentuk teksmisalnya
sumber
Ini adalah contoh yang bagus:
Baca dokumentasi ini untuk repr:
Berikut ini adalah dokumentasi untuk str:
sumber
__str__
(dibaca sebagai "string dunder (double-underscore)") dan__repr__
(dibaca sebagai "dunder-repper" (untuk "representasi")) keduanya adalah metode khusus yang mengembalikan string berdasarkan keadaan objek.__repr__
menyediakan perilaku cadangan jika__str__
tidak ada.Jadi pertama-tama seseorang harus menulis sebuah
__repr__
yang memungkinkan Anda untuk mengembalikan objek setara dari string yang dikembalikannya misalnya menggunakaneval
atau dengan mengetikkannya dalam karakter-untuk-karakter dalam shell Python.Kapan saja nanti, seseorang dapat menulis
__str__
untuk representasi string yang dapat dibaca pengguna dari instance, ketika seseorang percaya itu perlu.__str__
Jika Anda mencetak objek, atau meneruskannya ke
format
,,str.format
ataustr
, kemudian jika suatu__str__
metode didefinisikan, metode itu akan dipanggil, jika tidak,__repr__
akan digunakan.__repr__
The
__repr__
metode ini disebut oleh fungsi builtinrepr
dan apa yang bergema di shell python Anda ketika mengevaluasi sebuah ekspresi yang mengembalikan sebuah objek.Karena menyediakan cadangan untuk
__str__
, jika Anda hanya bisa menulis satu, mulailah dengan__repr__
Inilah bantuan bawaan pada
repr
:Artinya, untuk sebagian besar objek, jika Anda mengetik apa yang dicetak oleh
repr
, Anda harus dapat membuat objek yang setara. Tapi ini bukan implementasi standar.Implementasi Default dari
__repr__
Objek default
__repr__
adalah ( sumber C Python ) sesuatu seperti:Itu berarti secara default Anda akan mencetak modul dari objek, nama kelas, dan representasi heksadesimal dari lokasinya dalam memori - misalnya:
Informasi ini tidak terlalu berguna, tetapi tidak ada cara untuk mendapatkan bagaimana seseorang dapat secara akurat membuat representasi kanonik dari setiap contoh yang diberikan, dan itu lebih baik daripada tidak sama sekali, setidaknya memberi tahu kita bagaimana kita dapat secara unik mengidentifikasi itu dalam memori.
Bagaimana bisa
__repr__
bermanfaat?Mari kita lihat betapa bergunanya itu, menggunakan shell Python dan
datetime
objek. Pertama-tama kita perlu mengimpordatetime
modul:Jika kita memanggil
datetime.now
shell, kita akan melihat semua yang kita butuhkan untuk membuat ulang objek datetime yang setara. Ini dibuat oleh datetime__repr__
:Jika kita mencetak objek datetime, kita melihat format yang dapat dibaca manusia (sebenarnya, ISO). Ini diimplementasikan oleh datetime
__str__
:Ini adalah masalah sederhana untuk membuat ulang objek yang hilang karena kami tidak menetapkannya ke variabel dengan menyalin dan menempel dari
__repr__
output, dan kemudian mencetaknya, dan kami mendapatkannya dalam output yang dapat dibaca manusia sama seperti objek lainnya:Bagaimana cara menerapkannya?
Saat Anda berkembang, Anda mungkin ingin dapat mereproduksi objek dalam kondisi yang sama, jika memungkinkan. Ini, misalnya, adalah bagaimana mendefinisikan objek datetime
__repr__
( sumber Python ). Ini cukup rumit, karena semua atribut yang diperlukan untuk mereproduksi objek seperti itu:Jika Anda ingin objek Anda memiliki representasi yang lebih dapat dibaca manusia, Anda dapat menerapkan
__str__
selanjutnya. Inilah cara mengimplementasikan objek datetime ( sumber Python )__str__
, yang mudah dilakukan karena ia memiliki fungsi untuk menampilkannya dalam format ISO:Setel
__repr__ = __str__
?Ini adalah kritik terhadap jawaban lain di sini yang menyarankan pengaturan
__repr__ = __str__
.Pengaturan
__repr__ = __str__
konyol -__repr__
adalah fallback untuk__str__
dan__repr__
, ditulis untuk penggunaan pengembang dalam debugging, harus ditulis sebelum Anda menulis a__str__
.Anda membutuhkan
__str__
hanya ketika Anda membutuhkan representasi objek teks.Kesimpulan
Tentukan
__repr__
objek yang Anda tulis sehingga Anda dan pengembang lainnya memiliki contoh yang dapat direproduksi saat menggunakannya saat Anda mengembangkan. Tentukan__str__
kapan Anda membutuhkan representasi string yang dapat dibaca manusia.sumber
type(obj).__qualname__
?Pada halaman 358 dari buku Python scripting untuk ilmu komputasi oleh Hans Petter Langtangen, itu jelas menyatakan bahwa
__repr__
Tujuan di representasi string lengkap objek;__str__
adalah untuk mengembalikan string yang bagus untuk mencetak.Jadi, saya lebih suka memahaminya sebagai
dari sudut pandang pengguna meskipun ini adalah kesalahpahaman yang saya buat ketika belajar python.
Contoh kecil tapi bagus juga diberikan pada halaman yang sama sebagai berikut:
Contoh
sumber
repr
sebagai mereproduksi. Lebih baik menganggapnya sebagai mewakili.Terlepas dari semua jawaban yang diberikan, saya ingin menambahkan beberapa poin: -
1)
__repr__()
dipanggil ketika Anda cukup menulis nama objek pada konsol python interaktif dan tekan enter.2)
__str__()
dipanggil ketika Anda menggunakan objek dengan pernyataan cetak.3) Dalam hal, jika
__str__
tidak ada, maka cetak dan fungsi apa pun yang menggunakanstr()
panggilan__repr__()
.4)
__str__()
wadah, ketika dipanggil akan menjalankan__repr__()
metode elemen yang terkandung.5)
str()
dipanggil ke dalam__str__()
bisa berpotensi berulang tanpa kasus dasar, dan kesalahan pada kedalaman rekursi maksimum.6)
__repr__()
dapat memanggilrepr()
yang akan berusaha untuk menghindari rekursi tak terbatas secara otomatis, menggantikan objek yang sudah diwakili...
.sumber
Untuk membuatnya lebih sederhana:
__str__
digunakan untuk menunjukkan representasi string objek Anda agar mudah dibaca oleh orang lain.__repr__
digunakan untuk menunjukkan representasi string dari para objek.Katakanlah saya ingin membuat
Fraction
kelas di mana representasi string dari fraksi adalah '(1/2)' dan objek (kelas Fraksi) harus direpresentasikan sebagai 'Fraksi (1,2)'Jadi kita bisa membuat kelas Fraksi sederhana:
sumber
Dalam semua kejujuran,
eval(repr(obj))
tidak pernah digunakan. Jika Anda menemukan diri Anda menggunakannya, Anda harus berhenti, karenaeval
berbahaya, dan string adalah cara yang sangat tidak efisien untuk membuat serialisasi objek Anda (gunakanpickle
sebagai gantinya).Karena itu, saya akan merekomendasikan pengaturan
__repr__ = __str__
. Alasannya adalah bahwastr(list)
panggilanrepr
pada elemen (saya menganggap ini sebagai salah satu kelemahan desain terbesar dari Python yang tidak ditangani oleh Python 3). Hasil aktualrepr
mungkin tidak akan terlalu membantu sebagai hasil dariprint [your, objects]
.Untuk memenuhi syarat ini, dalam pengalaman saya, kasus penggunaan paling berguna dari
repr
fungsi ini adalah untuk meletakkan string di dalam string lain (menggunakan pemformatan string). Dengan cara ini, Anda tidak perlu khawatir lolos dari penawaran atau apa pun. Tetapi perhatikan bahwa tidak ada yangeval
terjadi di sini.sumber
eval(repr(obj))
adalah tes kewarasan dan aturan praktis - jika ini menciptakan kembali objek asli dengan benar maka Anda memiliki__repr__
implementasi yang layak . Itu tidak dimaksudkan bahwa Anda benar-benar membuat cerita bersambung objek dengan cara ini.eval
secara inheren tidak berbahaya. Apakah tidak lebih berbahaya daripadaunlink
,open
atau menulis ke file. Haruskah kita berhenti menulis ke file karena mungkin serangan jahat dapat menggunakan jalur file sewenang-wenang untuk memasukkan konten ke dalamnya? Semuanya berbahaya jika digunakan secara bodoh oleh orang bodoh. Idiocy berbahaya. Efek Dunning-Kruger berbahaya.eval
hanyalah sebuah fungsi.Dari Wiki Referensi Python (An Tidak Resmi) (salinan arsip) oleh effbot:
__str__
" Menghitung representasi string" informal "dari sebuah objek. Ini berbeda dari__repr__
yang tidak harus menjadi ekspresi Python yang valid: representasi yang lebih nyaman atau ringkas dapat digunakan sebagai gantinya. "sumber
__repr__
sama sekali tidak diperlukan untuk mengembalikan ekspresi Python vaild.str
- Membuat objek string baru dari objek yang diberikan.repr
- Mengembalikan representasi string kanonik objek.Perbedaan:
str ():
repr ():
sumber
Satu aspek yang hilang dalam jawaban lain. Memang benar bahwa secara umum polanya adalah:
__str__
: dapat dibaca manusia__repr__
: tidak ambigu, mungkin dapat dibaca melalui mesineval
Sayangnya, diferensiasi ini cacat, karena Python REPL dan juga IPython digunakan
__repr__
untuk mencetak objek dalam konsol REPL (lihat pertanyaan terkait untuk Python dan IPython ). Dengan demikian, proyek yang ditargetkan untuk pekerjaan konsol interaktif (misalnya, Numpy atau Pandas) telah mulai mengabaikan aturan di atas dan sebagai__repr__
gantinya memberikan implementasi yang dapat dibaca manusia .sumber
Dari buku Fluent Python :
sumber
Jawaban yang sangat baik sudah mencakup perbedaan antara
__str__
dan__repr__
, yang bagi saya bermuara pada yang sebelumnya dapat dibaca bahkan oleh pengguna akhir, dan yang terakhir menjadi berguna bagi pengembang. Mengingat itu, saya menemukan bahwa implementasi standar__repr__
sering gagal mencapai tujuan ini karena dihilangkan informasi yang berguna bagi pengembang.Untuk alasan ini, jika saya memiliki yang cukup sederhana
__str__
, saya biasanya hanya mencoba untuk mendapatkan yang terbaik dari kedua dunia dengan sesuatu seperti:sumber
Python lebih memilih ambiguitas daripada keterbacaan ,
__str__
panggilan darituple
panggilan yang berisi objek__repr__
, representasi "formal" dari suatu objek. Meskipun representasi formal lebih sulit dibaca daripada yang formal, itu tidak ambigu dan lebih kuat terhadap bug.sumber
__repr__
ketika (__str__
) tidak didefinisikan! Jadi kamu salah.Pendeknya:
sumber
Ketika
print()
dipanggil pada hasildecimal.Decimal(23) / decimal.Decimal("1.05")
angka mentah dicetak; output ini dalam bentuk string yang dapat dicapai dengan__str__()
. Jika kita cukup memasukkan ekspresi kita mendapatkandecimal.Decimal
output - output ini dalam bentuk representasional yang dapat dicapai dengan__repr__()
. Semua objek Python memiliki dua bentuk output. Bentuk string dirancang agar dapat dibaca oleh manusia. Bentuk representasional dirancang untuk menghasilkan keluaran yang jika diumpankan ke juru bahasa Python akan (bila mungkin) mereproduksi objek yang diwakili.sumber
__str__
dapat dipanggil pada objek dengan memanggilstr(obj)
dan harus mengembalikan string yang dapat dibaca manusia.__repr__
dapat dipanggil pada suatu objek dengan memanggilrepr(obj)
dan harus mengembalikan objek internal (bidang objek / atribut)Contoh ini dapat membantu:
sumber
Memahami
__str__
dan__repr__
secara intuitif dan permanen membedakan mereka sama sekali.__str__
mengembalikan string yang menyamarkan tubuh dari objek tertentu agar dapat dibaca mata__repr__
mengembalikan tubuh daging asli dari objek tertentu (mengembalikan dirinya sendiri) untuk mengidentifikasikan kerancuan.Lihat dalam contoh
Mengenai
__repr__
Kita dapat melakukan operasi aritmatika pada
__repr__
hasil dengan nyaman.jika menerapkan operasi pada
__str__
Tidak menghasilkan apa-apa selain kesalahan.
Contoh lain.
Semoga ini membantu Anda membangun alasan konkret untuk mengeksplorasi lebih banyak jawaban.
sumber
__str__
harus mengembalikan objek string sedangkan__repr__
dapat mengembalikan ekspresi python apa pun.__str__
implementasi hilang maka__repr__
fungsi digunakan sebagai fallback. Tidak ada fallback jika__repr__
implementasi fungsi hilang.__repr__
fungsi mengembalikan representasi String objek, kita bisa mengabaikan implementasi__str__
fungsi.Sumber: https://www.journaldev.com/22460/python-str-repr-functions
sumber
__repr__
digunakan di mana-mana, kecuali olehprint
danstr
metode (ketika a__str__
didefinisikan!)sumber