Ters işaretler python yorumlayıcısı için ne anlama geliyor: "num"


89

Liste anlayışlarıyla oynuyorum ve bu küçük parçaya başka bir sitede rastladım:

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

Bunu fark etmeden önce (yazarak) işlevi kopyalamak için birkaç dakika harcadım. `num`Bitin onu kırdığını .

Bu karakterlerin arasına bir ifade eklemek ne işe yarar? Gördüğüm kadarıyla str (num) ile eşdeğerdir. Ama zamanını belirlediğimde:

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

4.09s alırken:

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

2.43 saniye sürer.

Her ikisi de aynı sonuçları verir, ancak biri çok daha yavaştır. Burada neler oluyor?

DÜZENLEME: Garip bir şekilde ... repr()biraz daha yavaş sonuçlar veriyor `num`. 2.99s vs 2.43s. Python 2.6'yı kullanma (henüz 3.0'ı denemedim).


8
Skymind.com/~ocrow/python_string adresindeki "başka bir site" yi okuduktan sonra , benzer bir sorum vardı ve bu sayfayı buldum. Güzel soru ve güzel cevap :)
netvope

Yanıtlar:


124

Ters işaretler, için kullanımdan kaldırılmış bir takma addır repr(). Artık onları kullanmayın, sözdizimi Python 3.0'da kaldırıldı.

Ters tikleri kullanmak, kullanmaktan repr(num)veya num.__repr__()2.x sürümünden daha hızlı görünüyor . Sanırım bunun nedeni , sırasıyla genel ad alanında (için repr) veya nesnenin ad alanında (için __repr__) ek sözlük araması gerekmesidir .


disModülü kullanmak varsayımımı kanıtlıyor:

def f1(a):
    return repr(a)

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

def f3(a):
    return `a`

Demontaj gösterileri:

>>> 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   

f1Genel bir arama repr, f2bir öznitelik araması içerir __repr__, oysa geri dönüş operatörü ayrı bir işlem kodunda uygulanır. Sözlük araması ( LOAD_GLOBAL/ LOAD_ATTR) veya işlev çağrıları ( CALL_FUNCTION) için ek yük olmadığından , ters işaretler daha hızlıdır.

Sanırım Python çalışanları için ayrı bir düşük seviyeli işlem yapmanın repr()buna değmeyeceğine karar verdiler ve hem repr()ve hem de geri işaretlere sahip olmanın ilkeyi

"Bunu yapmanın bir ve tercihen tek bir açık yolu olmalı"

bu yüzden özellik Python 3.0'da kaldırıldı.


Backticks'i bazı işlev çağrılarıyla nasıl değiştirebileceğinizi bulmak istedim, ancak bu mümkün değil gibi görünüyor, yoksa değil mi?
Jiri

2
Ters işaretler yerine repr () kullanın. Geri işaretler repr () gelmek 3.0 için amortismana tabi sözdizimidir. Aslında, ANOTHER işlevini çağırmaktansa, ters işaretlerin görünümünü tercih ederim.
Dominic Bou-Samra

9
Ters vuruşların kullanımdan kaldırılmasının nedeni de `karakterinin kendisidir; yazmak zor olabilir (bazı klavyelerde), ne olduğunu görmek zor, Python kitaplarında doğru şekilde yazdırmak zor olabilir. Etc.
u0b34a0f6ae

4
@ kaizer.se: Bunu belirttiğiniz için teşekkürler. Muhtemelen ters vuruşları bırakmanın
Ferdinand Beyer

Bunun gönderildiği asıl soru, klavyemde ters işaretler bulamadığım içindir;) Tilde'nin altında, googling'den sonra görünüyor.
Dominic Bou-Samra

10

Backtick alıntı yapmak genellikle kullanışlı değildir ve Python 3'te ortadan kalkar.

Değeri ne olursa olsun, bu:

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

benim için backtick versiyonundan biraz daha hızlı. Ancak bu konuda endişelenmek muhtemelen erken bir optimizasyondur.


2
Neden bir adım geri gidip liste / yineleyici anlayışları yerine haritayı kullanasınız?
nikow

4
Aslında, timeitiçin ''.join(map(repr, xrange(0, 1000000)))olduğundan daha hızlı sonuç verir ''.join([repr(i) for i in xrange(0, 1000000)])(daha da kötüsü ''.join( (repr(i) for i in xrange(0, 1000000)) )). Biraz hayal kırıklığı yaratıyor ;-)
RedGlyph

8
Bobince'nin sonucu benim için şaşırtıcı değil. Genel bir kural olarak, Python'daki örtük döngüler açık olanlardan daha hızlıdır ve genellikle önemli ölçüde daha hızlıdır. mapsanal makinede yürütülen bir Python döngüsünden çok daha hızlı olan bir C döngüsü kullanılarak C'de gerçekleştirilir.
Ferdinand Beyer

7
Şaşırmadım, liste anlayışlarının itibarı için çok kötü (bu örnekte% 30'luk bir isabet). Ancak, bu gerçekten önemli olmadığı sürece, yüksek hızda bir kod kullanmaktansa, net olmasını tercih ederim, bu yüzden burada önemli bir şey yok. Bununla birlikte, map () işlevi bana belirsiz gelmiyor, LC bazen abartılıyor.
RedGlyph

4
mapbana tamamen açık ve öz görünüyor ve Python'u bile bilmiyorum.
Zenexer

1

Tahminimce numbu yöntemi tanımlamıyor __str__(), bu yüzden str()ikinci bir arama yapmak zorunda __repr__.

Ters vuruşlar doğrudan arar __repr__. Bu doğruysa, repr()ters işaretler yerine kullanmak size aynı sonuçları vermelidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.