Apa arti backticks bagi penerjemah python: `num`

89

Saya bermain-main dengan pemahaman daftar dan saya menemukan cuplikan kecil ini di situs lain:

return ''.join([`num` for num in xrange(loop_count)])

Saya menghabiskan beberapa menit mencoba untuk mereplikasi fungsi (dengan mengetik) sebelum menyadari `num`bit itu merusaknya.

Apa yang dilakukan dengan menyertakan pernyataan dalam karakter tersebut? Dari apa yang saya lihat itu setara dengan str (num). Tetapi ketika saya menghitung waktunya:

return ''.join([str(num) for num in xrange(10000000)])

Dibutuhkan 4,09s sedangkan:

return ''.join([`num` for num in xrange(10000000)])

membutuhkan 2,43s.

Keduanya memberikan hasil yang identik tetapi yang satu jauh lebih lambat. Apa yang terjadi disini?

EDIT: Anehnya ... repr()memberikan hasil yang sedikit lebih lambat dari `num`. 2,99s vs 2,43s. Menggunakan Python 2.6 (belum mencoba 3.0).

Dominic Bou-Samra
sumber
8
Setelah membaca "situs lain" di skymind.com/~ocrow/python_string , saya memiliki pertanyaan serupa dan menemukan halaman ini. Pertanyaan bagus dan jawaban bagus :)
netvope

Jawaban:

124

Backticks adalah alias yang tidak digunakan lagi untuk repr(). Jangan menggunakannya lagi, sintaksnya telah dihapus di Python 3.0.

Menggunakan backticks tampaknya lebih cepat daripada menggunakan repr(num)atau num.__repr__()dalam versi 2.x. Saya kira itu karena pencarian kamus tambahan diperlukan di namespace global (untuk repr), atau di namespace objek (untuk __repr__), masing-masing.


Menggunakan dismodul membuktikan asumsi saya:

def f1(a):
    return repr(a)

def f2(a):
    return a.__repr__()

def f3(a):
    return `a`

Pertunjukan pembongkaran:

>>> import dis
>>> dis.dis(f1)
  3           0 LOAD_GLOBAL              0 (repr)
              3 LOAD_FAST                0 (a)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE
>>> dis.dis(f2)
  6           0 LOAD_FAST                0 (a)
              3 LOAD_ATTR                0 (__repr__)
              6 CALL_FUNCTION            0
              9 RETURN_VALUE        
>>> dis.dis(f3)
  9           0 LOAD_FAST                0 (a)
              3 UNARY_CONVERT       
              4 RETURN_VALUE   

f1melibatkan pencarian global untuk repr, f2pencarian atribut __repr__, sedangkan operator backtick diimplementasikan dalam opcode terpisah. Karena tidak ada overhead untuk pencarian kamus ( LOAD_GLOBAL/ LOAD_ATTR) atau untuk pemanggilan fungsi ( CALL_FUNCTION), backticks lebih cepat.

Saya kira orang-orang Python memutuskan bahwa memiliki operasi tingkat rendah yang terpisah repr()tidak sepadan, dan memiliki keduanya repr()dan backticks melanggar prinsip

"Seharusnya ada satu - dan sebaiknya hanya satu --cara yang jelas untuk melakukannya"

jadi fitur tersebut telah dihapus dengan Python 3.0.

Ferdinand Beyer
sumber
Saya ingin menemukan, bagaimana Anda dapat mengganti backticks dengan beberapa pemanggilan fungsi, tetapi tampaknya itu tidak mungkin, atau apakah itu?
Jiri
2
Gunakan repr (), bukan backticks. Backticks adalah sintaks terdepresiasi untuk repr () come 3.0. Saya sebenarnya lebih suka tampilan backticks daripada memanggil fungsi ANOTHER.
Dominic Bou-Samra
9
Alasan backticks tidak digunakan lagi adalah karena `karakter itu sendiri; sulit untuk mengetik (pada beberapa keyboard), sulit untuk melihat apa itu, sulit untuk mencetak dengan benar di buku Python. Dll
u0b34a0f6ae
4
@ kaizer.se: Terima kasih telah menunjukkannya. Ini mungkin alasan utama untuk menghapus backticks, lihat pernyataan Guidos di arsip milis: mail.python.org/pipermail/python-ideas/2007-January/000054.html
Ferdinand Beyer
Pertanyaan asli yang diposting ini adalah karena saya tidak bisa menemukan backticks di keyboard saya;) Di bawah tilde tampaknya setelah googling.
Dominic Bou-Samra
10

Kutipan backtick umumnya tidak berguna dan hilang dengan Python 3.

Untuk apa nilainya, ini:

''.join(map(repr, xrange(10000000)))

sedikit lebih cepat daripada versi backtick untuk saya. Tetapi mengkhawatirkan hal ini mungkin merupakan pengoptimalan yang prematur.

bobince
sumber
2
Mengapa melangkah mundur dan menggunakan peta alih-alih pemahaman daftar / iterator?
nikow
4
Sebenarnya, memberikan timeithasil yang lebih cepat ''.join(map(repr, xrange(0, 1000000)))daripada untuk ''.join([repr(i) for i in xrange(0, 1000000)])(bahkan lebih buruk untuk ''.join( (repr(i) for i in xrange(0, 1000000)) )). Ini sedikit mengecewakan ;-)
RedGlyph
8
hasil bobince tidak mengejutkan saya. Sebagai aturan praktis, loop implisit dalam Python lebih cepat daripada yang eksplisit, seringkali jauh lebih cepat. mapdiimplementasikan di C, menggunakan loop C, yang jauh lebih cepat daripada loop Python yang dieksekusi di mesin virtual.
Ferdinand Beyer
7
Tidak heran juga, terlalu buruk untuk reputasi pemahaman daftar (dengan hit 30% dalam contoh ini). Tapi saya lebih suka memiliki kode yang jelas daripada sangat cepat kecuali ini benar-benar penting, jadi bukan masalah besar di sini. Karena itu, fungsi map () tidak menurut saya tidak jelas, LC terkadang berlebihan.
RedGlyph
4
maptampak sangat jelas dan ringkas bagi saya, dan saya bahkan tidak tahu Python.
Zenexer
1

Dugaan saya adalah itu numtidak menentukan metode __str__(), jadi str()harus melakukan pencarian kedua __repr__.

Para backticks mencari secara langsung __repr__. Jika itu benar, maka menggunakan repr()sebagai ganti backticks akan memberi Anda hasil yang sama.

Aaron Digulla
sumber