SORU
6 Mayıs 2015, ÇARŞAMBA


Neden `1000000000000000 aralığı(1000000000000001) bu kadar hızlı Python 3'te mi?

Aslında an object type in Python 3, range() işlevi, sinek, jeneratör benzer içeriğini oluşturur anladığım kadarıyla.

Bu durumda, burada beklenen aşağıdaki satırı için bir aşırı miktarda zaman, çünkü sipariş olup olmadığını belirlemek için 1 katrilyon ise Aralık, katrilyon değerleri ... oluşturulabilir:

1000000000000000 in range(1000000000000001)

Ayrıca: kaç tane ben eklemek olursa olsun, hesaplama daha fazla veya daha az süresi (temel olarak) anlık aynı miktarda alır gibi görünüyor.

Ayrıca bu gibi şeyler denedim, ama hesaplama hala neredeyse anında

1000000000000000000000 in range(0,1000000000000000000001,10) # count by tens

Eğer kendi aralığı benim işlevi yerine getirmeye çalıştım, sonuç çok güzel!!

def my_crappy_range(N):
    i = 0
    while i < N:
        yield i
        i  = 1
    return

Her şey çok hızlı yapar range() nesne kaputun altında ne işi var?


EDİT: Bu tahmin ettiğimden çok daha farklı bir konu oldu - range() optimizasyon arkasında tarihin biraz var gibi görünüyor.

Martijn Pieters' answer kendi bütünlüğü için seçildi, ama aynı zamanda range tam teşekküllü olmak için ne anlama geldiğini iyi bir tartışma için abarnert's first answer bkzsıraPython 3 ve bazı bilgi/uyarı __contains__ potansiyel tutarsızlık ile ilgili Python uygulamaları optimizasyon fonksiyonu. abarnert's other answer biraz daha detaya girer ve bu Python 3'te optimizasyon arkasındaki tarihi (ve Python 2 xrange optimizasyon eksikliği) ilgilenenler için bağlantılar sağlar. Cevap by poke by wim ilgilenenler için C kaynak kodu ve açıklamalar ilgili sağlayabilir.

CEVAP
6 Mayıs 2015, ÇARŞAMBA


3 range() Python nesne sayıları hemen üretmek değil; sayılar üreten akıllı bir sıra nesnesitalep üzerine. Başlat, Durdur ve adım değerleri vardır, sonra nesne üzerinde yineleme gibi bir sonraki tamsayı her yineleme hesaplanır.

Nesne de object.__contains__ hook ve . uygular ^em>hesaplarnumaranız varsa yelpazesini bir parçası. Hesaplama O(1) sabit zaman bir operasyon. Hiçbir zaman aralığında mümkün olan tüm tamsayılar taramak için bir ihtiyaç vardır.

range() object documentation:

Avantaj range tipi bir düzenli list tuple bir aralık nesnesi hep aynı (küçük) bir bellek miktarı, boyutu ne olursa olsun aralığını temsil eder (olarak sadece depolar start, stop step değerleri, hesaplama bireysel öğeleri ve alt aralıklar gerektiği gibi).

Yani en azından range() nesne yapar:

class my_range(object):
    def __init__(self, start, stop=None, step=1):
        if stop is None:
            start, stop = 0, start
        self.start, self.stop, self.step = start, stop, step
        if step < 0:
            lo, hi = stop, start
        else:
            lo, hi = start, stop
        self.length = ((hi - lo - 1) // abs(step))   1

    def __iter__(self):
        current = self.start
        if self.step < 0:
            while current > self.stop:
                yield current
                current  = self.step
        else:
            while current < self.stop:
                yield current
                current  = self.step

    def __len__(self):
        return self.length

    def __getitem__(self, i):
        if 0 <= i < self.length:
            return self.start   i * self.step
        raise IndexError('Index out of range: {}'.format(i))

    def __contains__(self, num):
        if self.step < 0:
            if not (self.stop < num <= self.start):
                return False
        else:
            if not (self.start <= num < self.stop):
                return False
        return (num - self.start) % self.step == 0

Bu hala eksik bazı şeyler bu bir gerçek range() destekler (gibi .index() .count() yöntem, karma, eşitlik testi, ya da Dilimleme), ama iyi bir fikir.

Ben de basitleştirilmiş __contains__ uygulama için sadece odaklanmak tamsayı testleri; eğer gerçek bir range() nesnesi olmayan bir tamsayı değeri (alt sınıflar da dahil olmak üzere int), yavaş tarama başlatılan görmek için bir maç, sadece bir çevreleme test karşı bir liste tüm bulunan değerler. Bu sadece tamsayılar ile eşitliği test destek oluyor ama tamsayı aritmetik destek vermesi beklenmiyor da diğer sayısal türlerini desteklemek için devam etmek için yapıldı. Çevreleme testi uygulayan Python issue orijinal bakın.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Android Developers

    Android Deve

    9 Kasım 2007
  • MandMEvangelists

    MandMEvangel

    28 Ocak 2008
  • Truc Minh

    Truc Minh

    23 Ocak 2011

İLGİLİ SORU / CEVAPLAR