Lebih
Perbedaan antara __str__ dan __k__?
Apa perbedaan antara __str__
dan __k__
di Python?
2527
22
Apa perbedaan antara __str__
dan __k__
di Python?
Alex diringkas dengan baik, tetapi, yang mengejutkan, adalah terlalu ringkas.
Pertama, izinkan saya mengulangi poin-poin utama dalam Alex pos:
__k__
tujuannya adalah untuk menjadi jelas__str__
tujuannya adalah untuk dapat dibaca__str__
menggunakan benda-benda yang terkandung'__k__
Implementasi standar adalah sia-sia
Ini adalah sebagian besar mengejutkan karena Python default cenderung cukup berguna. Namun, dalam kasus ini, memiliki default untuk
__k__
yang akan bertindak seperti:akan terlalu berbahaya (misalnya, terlalu mudah untuk masuk ke rekursi tak terbatas jika objek referensi satu sama lain). Jadi Python polisi. Perhatikan bahwa ada satu default yang benar: jika
__k__
didefinisikan, dan__str__
tidak, objek akan berperilaku seolah-olah__str__=__k__
.Ini berarti, dalam istilah sederhana: hampir setiap objek yang melaksanakan harus memiliki fungsional
__k__
yang dapat digunakan untuk memahami objek. Menerapkan__str__
adalah opsional: lakukan jika anda perlu "cukup print" fungsi (misalnya, digunakan oleh report generator).Tujuan dari
__k__
harus tidak ambiguMari saya datang langsung keluar dan mengatakan itu — saya tidak percaya pada debugger. Aku tidak benar-benar tahu bagaimana menggunakan debugger, dan belum pernah digunakan satu serius. Selain itu, saya percaya bahwa kesalahan besar dalam debugger adalah sifat dasar mereka — sebagian besar kegagalan saya debug terjadi sebuah waktu yang lama lalu, di sebuah galaksi jauh jauh. Ini berarti bahwa saya tidak percaya, dengan semangat keagamaan, dalam penebangan. Logging adalah nyawa dari setiap yang layak api-dan-lupakan sistem server. Python membuatnya mudah untuk log: mungkin dengan beberapa proyek tertentu pembungkus, semua yang anda butuhkan adalah
Tapi anda harus melakukan langkah terakhir — pastikan setiap benda yang anda telah melaksanakan berguna cetak ulang, sehingga kode seperti itu hanya dapat bekerja. Ini adalah mengapa "eval" hal yang muncul: jika anda memiliki informasi yang cukup sehingga
eval(repr(c))==c
, yang berarti anda tahu semuanya ada untuk mengetahui tentangc
. Jika itu cukup mudah, setidaknya dalam cara kabur, melakukannya. Jika tidak, pastikan anda memiliki informasi yang cukup tentangc
pula. Saya biasanya menggunakan eval-seperti format:"MyClass(ini=%r,yaitu=%r)" % (self.ini,mandiri.itu)
. Itu tidak berarti bahwa anda benar-benar dapat membangun MyClass, atau bahwa mereka adalah benar konstruktor argumen — tapi itu adalah bentuk yang berguna untuk mengungkapkan "ini adalah semua yang anda perlu tahu tentang hal ini".Catatan: saya menggunakan
%r
di atas, bukan%s
. Anda selalu ingin menggunakank()
[atau%r
pemformatan karakter, ekuivalen] dalam__k__
pelaksanaan, atau anda mengalahkan tujuan dari cetak ulang. Anda ingin menjadi mampu membedakanMyClass(3)
danMyClass("3")
.Tujuan dari
__str__
dapat dibacaSecara khusus, hal ini tidak dimaksudkan untuk menjadi jelas — pemberitahuan bahwa
str(3)==str("3")
. Demikian juga, jika anda menerapkan IP abstraksi, memiliki str itu terlihat seperti 192.168.1.1 baik-baik saja. Pada saat pelaksanaan tanggal/waktu abstraksi, str dapat "2010/4/12 15:35:22", dll. Tujuannya adalah untuk mewakili dalam cara yang user, bukan seorang programmer, anda akan ingin untuk membacanya. Memotong berguna digit, berpura-pura menjadi beberapa kelas lainnya — selama ini mendukung keterbacaan, itu adalah sebuah perbaikan.Wadah
__str__
menggunakan benda-benda yang terkandung'__k__
Hal ini tampaknya mengejutkan, bukan? Itu adalah sedikit, tapi bagaimana akan dibaca
menjadi? Tidak sangat. Secara khusus, string dalam wadah akan menemukan itu terlalu mudah untuk mengganggu representasi string. Dalam menghadapi ambiguitas, ingat, Python menolak godaan untuk menebak. Jika anda ingin atas perilaku ketika anda mencetak daftar, hanya
(anda mungkin bisa juga mencari tahu apa yang harus dilakukan tentang kamus.
Ringkasan
Menerapkan
__k__
untuk semua kelas menerapkan. Ini harus menjadi sifat kedua. Menerapkan__str__
jika anda pikir itu akan berguna untuk memiliki sebuah string versi yang keliru pada sisi keterbacaan.Saya rule of thumb:
__k__
untuk pengembang,__str__
adalah untuk pelanggan.Kecuali anda secara khusus undang-undang untuk memastikan jika tidak, sebagian besar kelas don't memiliki hasil yang berguna untuk:
Seperti yang anda lihat-tidak ada perbedaan, dan tidak ada info di luar kelas dan objek's
id
. Jika anda hanya menimpa satu dari dua...:seperti yang anda lihat, jika anda menimpa
__k__
, yang's JUGA digunakan untuk__str__
, tetapi tidak sebaliknya.Penting lainnya tidbits untuk mengetahui:
__str__
pada built-pada wadah menggunakan__k__
, BUKAN__str__
, untuk item di dalamnya. Dan, meskipun kata-kata pada subjek yang ditemukan di khas docs, hampir tidak ada orang yang mengganggu membuat__k__
objek menjadi string yangeval
dapat digunakan untuk membangun sebuah objek yang sama (it's hanya terlalu keras, DAN tidak tahu bagaimana yang relevan modul adalah benar-benar diimpor membuatnya benar-benar datar keluar mustahil).Jadi, saran saya: fokus pada pembuatan
__str__
cukup terbaca-manusia, dan__k__
sebagai jelas seperti yang anda bisa, bahkan jika itu mengganggu fuzzy tercapai tujuan membuat__k__
's kembali nilai yang dapat diterima sebagai masukan untuk__eval__
!__k__
: representasi dari objek python biasanya eval akan mengubahnya kembali ke objek yang__str__
: adalah apapun yang anda pikirkan adalah bahwa objek dalam bentuk teksmisalnya
Berikut adalah contoh yang baik:
Baca dokumentasi ini untuk repr:
Berikut ini merupakan dokumentasi untuk str:
__str__
(baca sebagai "ddi bawah (double-garis bawah) string") dan__k__
(baca sebagai "ddi bawah-repper" ("representasi")) adalah metode khusus yang mengembalikan string berdasarkan keadaan objek.__k__
menyediakan cadangan perilaku jika__str__
hilang.Jadi yang pertama harus menulis
__k__
yang memungkinkan anda untuk reinstantiate setara objek dari string itu kembali misalnya dengan menggunakaneval
atau dengan mengetik dalam karakter-untuk-karakter di Python shell.Pada waktu kemudian, seseorang dapat menulis
__str__
untuk pengguna-dibaca representasi string contoh, ketika seseorang percaya itu menjadi diperlukan.__str__
Jika anda mencetak sebuah objek, atau menyebarkannya ke
format
,str.format
, ataustr
, maka jika a__str__
metode didefinisikan, bahwa metode yang akan disebut, jika tidak,__k__
akan digunakan.__k__
The
__k__
metode ini disebut dengan fungsi bawaank
dan apa yang dikumandangkan pada python shell ketika mengevaluasi ekspresi yang mengembalikan sebuah objek.Karena memberikan cadangan untuk
__str__
, jika anda hanya bisa menulis satu, mulai dengan__k__
Berikut ini's builtin bantuan pada
k
:Itu adalah, untuk sebagian besar benda-benda, jika anda mengetik di tempat yang dicetak oleh
k
, anda harus mampu menciptakan aplikasi yang setara objek. Tapi ini bukan default implementasi.Default Pelaksanaan
__k__
Objek default
__k__
adalah (C Python sumber) sesuatu seperti:Itu berarti secara default anda'll cetak modul objek dari, nama kelas, dan representasi heksadesimal lokasi di memori - misalnya:
Informasi ini isn't sangat berguna, tapi ada's tidak ada cara untuk memperoleh bagaimana seseorang bisa secara akurat membuat kanonik representasi dari setiap contoh yang diberikan, dan itu's lebih baik daripada tidak, setidaknya memberitahu kita bagaimana kita dapat mengidentifikasi secara unik dalam memori.
Bagaimana bisa
__k__
menjadi berguna?Let's melihat bagaimana berguna itu dapat, dengan menggunakan Python shell dan
datetime
benda-benda. Pertama kita perlu mengimpordatetime
module:Jika kita sebut
datetime.sekarang
di shell, kami'll melihat segala sesuatu yang kita butuhkan untuk menciptakan aplikasi yang setara datetime objek. Ini dibuat oleh datetime__k__
:Jika kami mencetak datetime objek, kita melihat yang baik yang dapat dibaca manusia (pada kenyataannya, ISO) format. Hal ini dilaksanakan oleh datetime's
__str__
:Ini adalah masalah sederhana untuk menciptakan objek kami kalah karena kami tak't menetapkan variabel dengan menyalin dan menyisipkan dari
__k__
output, dan kemudian mencetaknya, dan kita mendapatkannya di saat yang sama output yang dapat dibaca manusia sebagai objek yang lain:Bagaimana cara menerapkannya?
Seperti yang anda're berkembang, anda'll ingin dapat mereproduksi benda-benda dalam negara yang sama, jika mungkin. Ini, misalnya, adalah bagaimana datetime objek mendefinisikan
__k__
(Python sumber). Hal ini cukup kompleks, karena semua atribut yang diperlukan untuk mereproduksi objek tersebut:Jika anda ingin objek anda untuk memiliki lebih banyak dibaca manusia representasi, anda dapat menerapkan
__str__
berikutnya. Berikut ini's bagaimana datetime object (Python sumber) mengimplementasikan__str__
, yang itu tidak mudah karena sudah memiliki fungsi untuk menampilkannya dalam format ISO:Set
__k__ = __str__
?Ini adalah sebuah kritik jawaban lain di sini yang menunjukkan pengaturan
__k__ = __str__
.Pengaturan
__k__ = __str__
konyol -__k__
fallback untuk__str__
dan__k__
, yang ditulis untuk pengembang penggunaan dalam debugging, harus ditulis sebelum anda menulis__str__
.Anda perlu
__str__
hanya ketika anda membutuhkan representasi tekstual dari objek.Kesimpulan
Mendefinisikan
__k__
untuk benda-benda yang anda tulis, sehingga anda dan pengembang lain telah direproduksi contoh ketika menggunakannya sebagai anda mengembangkan. Mendefinisikan__str__
ketika anda perlu dibaca manusia representasi string dari itu.Terlepas dari semua jawaban yang diberikan, saya ingin menambahkan beberapa poin :-
__k__()
dipanggil ketika anda hanya menulis objek's nama pada interaktif python console dan tekan enter.__str__()
dipanggil ketika anda menggunakan objek dengan mencetak pernyataan.Dalam kasus ini, jika
__str__
hilang, maka cetak dan fungsi menggunakanstr()
memanggil__k__()
dari objek.__str__()
kontainer, ketika dipanggil akan mengeksekusi__k__()
metode terkandung unsur-unsur.str()
yang disebut dalam__str__()
berpotensi recurse tanpa dasar kasus, dan kesalahan maksimum kedalaman rekursi.__k__()
dapat memanggilrepr()
yang akan mencoba untuk menghindari rekursi tak terbatas secara otomatis, mengganti yang sudah diwakili objek dengan...
.Pada halaman 358 buku Python scripting untuk komputasi ilmu oleh Hans Petter Langtangen, hal ini jelas menyatakan bahwa
__k__
bertujuan lengkap representasi string dari objek;__str__
adalah untuk mengembalikan bagus string untuk mencetak.Jadi, saya lebih memilih untuk memahami mereka sebagai
dari pengguna's point of view meskipun ini adalah kesalahpahaman yang saya buat ketika belajar python.
Kecil tapi contoh yang baik juga diberikan pada halaman yang sama sebagai berikut:
Contoh
Di semua kejujuran,
eval(repr(obj))
adalah tidak pernah digunakan. Jika anda menemukan diri anda menggunakan ini, anda harus berhenti, karenaeval
lebih berbahaya, dan string adalah sangat tidak efisien cara untuk membuat objek anda (gunakanacar
bukan).Oleh karena itu, saya akan merekomendasikan pengaturan
__k__ = __str__
. Alasannya adalah bahwastr(daftar)
panggilank
pada unsur-unsur (saya menganggap hal ini menjadi salah satu desain kelemahan dari Python yang tidak ditangani oleh Python 3). Sebenarnyarepr
mungkin tidak akan sangat bermanfaat sebagai output daricetak [anda, benda-benda]
.Untuk memenuhi syarat ini, dalam pengalaman saya, yang paling berguna menggunakan kasus
repr
fungsi adalah untuk menempatkan string di dalam string lain (menggunakan string format). Dengan cara ini, anda don't perlu khawatir tentang melarikan diri kutipan atau apa pun. Tetapi perhatikan bahwa tidak adaeval
terjadi di sini.Sederhananya:
__str__
digunakan untuk menunjukkan representasi string dari objek anda untuk membaca mudah oleh orang lain.__k__
digunakan untuk menunjukkan representasi string dari the objek.Let's mengatakan saya ingin membuat
Fraksi
kelas di mana representasi string dari fraksi '(1/2)' dan objek (Fraksi class) akan direpresentasikan sebagai 'Sebagian kecil (1,2)'Jadi kita dapat membuat sederhana Pecahan kelas:
Dari an (tidak Resmi) Python Referensi Wiki (salinan arsip) oleh effbot:
__str__
"menghitung "informal" representasi string dari sebuah objek. Ini berbeda dari__k__
dalam hal itu tidak harus yang valid Python ungkapan: lebih nyaman atau representasi ringkas dapat digunakan sebagai gantinya."Salah satu aspek yang hilang pada jawaban yang lain. It's benar bahwa secara umum pola ini:
__str__
: human-readable__k__
: jelas, mungkin mesin yang dapat dibaca melaluieval
Sayangnya, diferensiasi ini adalah cacat, karena Python REPL dan juga IPython menggunakan
__k__
untuk mencetak benda-benda di REPL konsol (lihat pertanyaan terkait untuk Python dan IPython). Dengan demikian, proyek-proyek yang ditargetkan untuk konsol interaktif pekerjaan (misalnya, Numpy atau Panda) sudah mulai mengabaikan aturan di atas dan memberikan terbaca-manusia__k__
pelaksanaan sebaliknya.str
- Menciptakan sebuah string baru objek dari objek tertentu.k
- Kembali kanonik representasi string dari objek.Perbedaan:
str():
repr():
Dari buku Menguasai Python:
Setiap jawaban yang sudah menutupi perbedaan antara
__str__
dan__k__
, yang bagi saya bermuara pada bekas yang mudah dibaca bahkan oleh pengguna akhir, dan yang terakhir menjadi berguna mungkin untuk pengembang. Mengingat itu, saya menemukan bahwa default pelaksanaan__k__
sering gagal untuk mencapai tujuan ini karena menghilangkan informasi yang berguna untuk pengembang.Untuk alasan ini, jika saya punya cukup sederhana
__str__
, saya biasanya hanya mencoba untuk mendapatkan yang terbaik dari kedua dunia dengan sesuatu seperti:Python nikmat unambiguity atas readability, yang
__str__
panggilantupel
panggilan yang terkandung benda'__k__
, dengan"formal" representasi dari sebuah objek. Meskipun representasi formal lebih sulit untuk dibaca daripada yang informal, lebih jelas dan lebih kuat terhadap bug.Ketika
cetak()
disebut pada hasildesimal.Desimal(23) / desimal.Desimal("1.05")
baku nomor dicetak; output ini adalah string formulir yang dapat dicapai dengan__str__()
. Jika kita hanya memasukkan ekspresi kita mendapatkandesimal.Desimal
output — output ini adalah representasi bentuk yang dapat dicapai dengan__k__()
. Semua Python benda-benda yang memiliki dua bentuk keluaran. String bentuk ini dirancang untuk bisa terbaca-manusia. Representasi bentuk ini dirancang untuk menghasilkan output yang jika dimasukkan ke Python interpreter akan (bila mungkin) mereproduksi mewakili objek.Singkatnya:
__str__
dapat dipanggil pada sebuah objek dengan memanggilstr(obj)
dan harus kembali dibaca manusia string.__k__
dapat dipanggil pada sebuah objek dengan memanggilrepr(obj)
dan harus mengembalikan internal objek (object field/atribut)Contoh ini dapat membantu:
Memahami
__str__
dan__k__
intuitif dan permanen membedakan mereka semua.__str__
mengembalikan string yang menyamar tubuh dari objek yang diberikan untuk dibaca dari mata__k__
kembali daging tubuh dari objek yang diberikan (kembali) untuk unambiguity untuk mengidentifikasi.Lihat di contoh
Untuk
__k__
Kita dapat melakukan operasi aritmatika pada
__k__
hasil bagi.jika menerapkan operasi pada
__str__
Mengembalikan apa-apa tapi error.
Contoh lain.
Semoga ini bisa membantu anda membangun beton dasar untuk mengeksplorasi lebih banyak jawaban.