Pertanyaan Mengapa Python memiliki fungsi format serta metode format


Itu format fungsi dalam builtins tampaknya seperti bagian dari str.format metode yang digunakan khusus untuk kasus pemformatan objek tunggal.

misalnya.

>>> format(13, 'x')
'd'

tampaknya lebih disukai

>>> '{0:x}'.format(13)
'd'

dan IMO memang terlihat lebih bagus, tetapi mengapa tidak digunakan saja str.format dalam setiap kasus untuk membuat semuanya lebih sederhana? Keduanya diperkenalkan di 2.6 jadi pasti ada alasan bagus untuk memiliki keduanya sekaligus, apa itu?

Edit: Saya bertanya tentang str.format dan format, bukan mengapa kita tidak memiliki (13).format


32
2018-05-22 04:33


asal


Jawaban:


kupikir format dan str.format melakukan hal yang berbeda. Meskipun Anda bisa menggunakannya str.format untuk keduanya, masuk akal untuk memiliki versi terpisah.

Tingkat teratas format fungsi adalah bagian dari "protokol pemformatan" baru yang didukung oleh semua objek. Ini hanya memanggil __format__ metode objek itu berlalu, dan mengembalikan string. Ini adalah tugas tingkat rendah, dan gaya Python biasanya memiliki fungsi bawaan untuk itu. Jawaban Paulo Scardine menjelaskan beberapa alasan untuk ini, tetapi saya tidak berpikir itu benar-benar membahas perbedaan antara apa format dan str.format melakukan.

Itu str.format Metodenya sedikit lebih tinggi, dan juga sedikit lebih kompleks. Tidak hanya dapat memformat beberapa objek menjadi satu hasil, tetapi juga dapat menyusun ulang, mengulangi, mengindeks, dan melakukan berbagai transformasi lainnya pada objek. Jangan hanya memikirkan "{}".format(obj). str.format benar-benar dirancang untuk lebih banyak tentang tugas-tugas yang rumit, seperti ini:

"{1} {0} {1!r}".format(obj0, obj1) # reorders, repeats, and and calls repr on obj1
"{0.value:.{0.precision}f}".format(obj) # uses attrs of obj for value and format spec
"{obj[name]}".format(obj=my_dict) # takes argument by keyword, and does an item lookup

Untuk pemformatan tingkat rendah dari setiap item, str.format bergantung pada mesin yang sama dari protokol format, sehingga dapat memfokuskan upaya sendiri pada hal-hal tingkat yang lebih tinggi. Saya ragu itu benar-benar memanggil builtin format, daripada argumennya __format__ metode, tapi itu merupakan detail implementasi.

Sementara ("{"+format_code+"}").format(obj) dijamin memberikan hasil yang sama dengan format(obj, format_code)Saya menduga yang terakhir akan sedikit lebih cepat, karena tidak perlu mem-parsing string format untuk memeriksa hal-hal yang rumit. Namun overhead mungkin hilang dalam kebisingan dalam program nyata.

Ketika datang ke penggunaan (termasuk contoh pada Stack Overflow), Anda mungkin melihat lebih banyak str.format gunakan hanya karena beberapa programmer tidak mengetahuinya format, yang baru dan cukup tidak jelas. Sebaliknya, sulit dihindari str.format (kecuali Anda telah memutuskan untuk tetap dengan % operator untuk semua format Anda). Jadi, kemudahan (bagi Anda dan rekan programmer Anda) dari pemahaman a str.format panggilan mungkin melebihi pertimbangan kinerja apa pun.


6
2018-05-22 22:37



tldr;  format telepon saja obj.__format__ dan digunakan oleh str.format metode yang bahkan melakukan hal yang lebih tinggi. Untuk tingkat yang lebih rendah, masuk akal untuk mengajarkan suatu objek cara memformat dirinya sendiri.

Ini hanya gula sintaksis

Fakta bahwa fungsi ini berbagi nama dan spesifikasi format dengan str.format bisa menyesatkan. Keberadaan str.format mudah untuk dijelaskan: itu interpolasi string yang kompleks (menggantikan yang lama % operator); formatdapat memformat objek tunggal sebagai string, bagian terkecil dari str.format spesifikasi. Jadi, mengapa kita butuh format?

Itu format fungsi adalah alternatif dari obj.format('fmt') konstruk ditemukan di beberapa OO bahasa. Keputusan ini konsisten dengan alasan untuk len (tentang mengapa Python menggunakan fungsi len(x) bukannya sebuah properti x.length seperti Javascript atau Ruby).

Ketika suatu bahasa mengadopsi obj.format('fmt') membangun (atau obj.length, obj.toString dan sebagainya), kelas dicegah dari memiliki atribut yang disebut format (atau length, toString, Anda mendapatkan ide) - jika tidak, itu akan membayangi metode standar dari bahasa. Dalam hal ini, desainer bahasa menempatkan beban untuk mencegah bentrokan nama pada programmer.

Python sangat menyukai PoLA dan mengadopsi __dunder__ (menggarisbawahi) konvensi untuk built-in untuk meminimalkan kemungkinan konflik antara atribut yang ditentukan pengguna dan bahasa built-in. Begitu obj.format('fmt') menjadi obj.__format__('fmt'), dan tentu saja Anda bisa menelepon obj.__format__('fmt') dari pada format(obj, 'fmt') (cara yang sama Anda bisa menelepon obj.__len__() dari pada len(obj)).

Menggunakan contoh Anda:

>>> '{0:x}'.format(13)
'd'
>>> (13).__format__('x')
'd'
>>> format(13, 'x')
'd'

Mana yang lebih bersih dan lebih mudah diketik? Desain Python sangat pragmatis, tidak hanya bersih tetapi juga selaras dengan Python diketik bebek mendekat ke OO dan memberi kebebasan kepada desainer bahasa untuk mengubah / memperluas implementasi yang mendasarinya tanpa melanggar kode warisan.

Itu PEP 3101 memperkenalkan yang baru str.format metode dan format built-in tanpa komentar tentang alasan untuk format berfungsi, tetapi pelaksanaannya jelas saja gula sintaksis:

def format(value, format_spec):
    return value.__format__(format_spec)

Dan di sini saya mengistirahatkan kasus saya.

Apa yang Guido katakan tentang itu (atau apakah itu resmi?)

Mengutip yang sangat BDFL tentang len:

Pertama-tama, saya memilih len(x) lebih x.len() untuk HCI alasan (def __len__() datang jauh kemudian). Sebenarnya ada dua alasan yang saling terkait HCI:

(A) Untuk beberapa operasi, awalan notasi hanya membaca lebih baik daripada postfix - prefix (dan infix!) Operasi memiliki tradisi panjang dalam matematika yang suka notasi di mana visual membantu para matematikawan memikirkan masalah. Bandingkan dengan mudah kita menulis ulang rumus seperti x*(a+b) ke x*a + x*b untuk kecanggungan melakukan hal yang sama menggunakan notasi OO mentah.

(B) Ketika saya membaca kode yang mengatakan len(x) Saya tahu bahwa itu meminta panjang sesuatu. Ini memberi tahu saya dua hal: hasilnya adalah bilangan bulat, dan argumennya adalah semacam wadah. Sebaliknya, ketika saya membaca x.len(), Saya harus sudah tahu itu x adalah semacam wadah yang mengimplementasikan antarmuka atau mewarisi dari kelas yang memiliki standar len(). Saksikan kebingungan yang kadang-kadang kita miliki ketika kelas yang tidak menerapkan pemetaan memiliki get() atau keys() metode, atau sesuatu yang tidak memiliki file write() metode.

Mengatakan hal yang sama dengan cara lain, saya melihat 'len‘Sebagai operasi yang sudah ada. Saya tidak suka kehilangan itu. / ... /

sumber: pyfaq@effbot.org (posting asli sini juga pertanyaan asli Guido sedang menjawab). Abarnert disarankan juga:

Ada alasan tambahan tentang len di FAQ Desain dan Sejarah. Meskipun itu tidak lengkap atau sebagus sebuah jawaban, itu tidak bisa disangkal resmi. - abarnert

Apakah ini masalah praktis atau sintaksis saja?

Ini adalah kepedulian yang sangat praktis dan nyata dalam bahasa seperti Python, Rubi atau Javascript karena dalam bahasa yang diketik secara dinamis setiap objek yang dapat diredam secara efektif merupakan namespace, dan konsep metode atau atribut privat adalah masalah konvensi. Mungkin saya tidak bisa membuatnya lebih baik daripada abarnert dalam komentarnya:

Juga, sejauh masalah polusi namespace dengan Ruby dan JS, perlu diketahui bahwa ini adalah masalah yang melekat dengan bahasa-bahasa yang diketik secara dinamis. Dalam bahasa-bahasa yang diketik secara statis beragam seperti Haskell dan C ++, fungsi-fungsi bebas jenis khusus tidak hanya mungkin, tetapi juga idiomatik. (Lihat The Prinsip Antarmuka.) Namun dalam bahasa yang dikenali secara dinamis seperti Ruby, JS, dan Python, fungsi gratis harus universal. Bagian besar dari desain bahasa / perpustakaan untuk bahasa dinamis adalah memilih kumpulan fungsi yang tepat.

Misalnya, saya baru saja pergi Ember.js mendukung Angular.js karena Saya lelah konflik namespace di Ember; Sudut menangani ini menggunakan strategi Python-seperti elegan dari awalan metode built-in (dengan $thing di Angular, alih-alih menggarisbawahi seperti python), sehingga mereka tidak bertentangan dengan metode dan properti yang ditentukan pengguna. Ya, semuanya __thing__ tidak terlalu cantik tapi aku senang Python mengambil pendekatan ini karena sangat eksplisit dan menghindari PoLA kelas bug tentang bentrokan namespace objek.


37