Len () fonksiyonunun maliyeti


Yanıtlar:


341

It adlı Ç (1) Eğer açıkladığım tüm türüne artı - (çok hızlı sabit zaman, elemanın gerçek uzunluğunun bağlı değil) setve bu şekilde diğerlerinin array.array.


17
Yararlı cevap için teşekkürler! Bunun böyle olmadığı yerel türler var mı?
mvanveen


84

Tüm bu nesneler kendi uzunluklarını takip eder. Uzunluğu ayıklama süresi küçüktür (büyük O gösterimlerinde O (1)) ve çoğunlukla [kaba terimler, C terimleriyle değil, Python terimleriyle yazılmıştır]: sözlükte "len" kelimesini arayın ve nesnenin __len__yöntemini arayacak ve bunu çağıracak built_in len fonksiyonu ... tek yapması gerekenreturn self.length


3
Bunun en uygun cevap olduğunu düşünüyorum, çünkü bu uygulama ayrıntılarını anlıyor.
AK

neden lengthsözlükte gösterilmiyor dir(list)?
ViFI

aradığım şey buydu
Visakh Vijayan

@ViFI Çünkü bu sadece bir örnek. Gösterilen list.lenghtdeğişken Python değil C olarak uygulanır.
Kowalski

73

Aşağıdaki ölçümler len(), sıkça kullanılan veri yapıları için O (1) kanıtıdır .

Şununla ilgili bir not timeit: -sBayrak kullanıldığında ve timeitilk dizeye iki dize geçirildiğinde yalnızca bir kez yürütülür ve zamanlanmaz.

Liste:

$ python -m timeit -s "l = range(10);" "len(l)"
10000000 loops, best of 3: 0.0677 usec per loop

$ python -m timeit -s "l = range(1000000);" "len(l)"
10000000 loops, best of 3: 0.0688 usec per loop

Kayıt düzeni:

$ python -m timeit -s "t = (1,)*10;" "len(t)"
10000000 loops, best of 3: 0.0712 usec per loop

$ python -m timeit -s "t = (1,)*1000000;" "len(t)"
10000000 loops, best of 3: 0.0699 usec per loop

Dize:

$ python -m timeit -s "s = '1'*10;" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop

$ python -m timeit -s "s = '1'*1000000;" "len(s)"
10000000 loops, best of 3: 0.0686 usec per loop

Sözlük (sözlük anlama 2.7 ve üstü sürümlerde mevcuttur):

$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(10))};" "len(d)"
10000000 loops, best of 3: 0.0711 usec per loop

$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(1000000))};" "len(d)"
10000000 loops, best of 3: 0.0727 usec per loop

Dizi:

$ python -mtimeit -s"import array;a=array.array('i',range(10));" "len(a)"
10000000 loops, best of 3: 0.0682 usec per loop

$ python -mtimeit -s"import array;a=array.array('i',range(1000000));" "len(a)"
10000000 loops, best of 3: 0.0753 usec per loop

Set (set üstü kavrama 2.7 ve üstü sürümlerde mevcuttur):

$ python -mtimeit -s"s = {i for i in range(10)};" "len(s)"
10000000 loops, best of 3: 0.0754 usec per loop

$ python -mtimeit -s"s = {i for i in range(1000000)};" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop

deque:

$ python -mtimeit -s"from collections import deque;d=deque(range(10));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop

$ python -mtimeit -s"from collections import deque;d=deque(range(1000000));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop

1
Zaten bildiğimizi göstermesine rağmen bu bir kriter kadar iyi değil. Bunun nedeni (10) ve (1000000) aralığının O (1) olması gerekmemesidir.
Bilinmiyor

3
Bu açık ara en iyi cevap. Birisinin sürekli zamanı fark etmemesi durumunda bir sonuç eklemelisiniz.
santiagobasulto

4
Yorum için teşekkürler. O (1) karmaşıklığı hakkında bir not ekledim len()ve ayrıca -sbayrağı uygun şekilde kullanmak için ölçümleri sabitledim .
mechanical_meat

Uzunluğun bir değişkene kaydedilmesinin önemli miktarda hesaplama süresinden tasarruf edebileceğini unutmamak önemlidir: python -m timeit -s "l = range(10000);" "len(l); len(l); len(l)"döngü başına 223 nsec döngü başına python -m timeit -s "l = range(100);" "len(l)"66,2 nsec
Radostin Stoyanov

16

len bir O (1) 'dir, çünkü RAM'inizde listeler tablo olarak saklanır (bitişik adresler dizisi). Masanın ne zaman durduğunu bilmek için bilgisayarın iki şeye ihtiyacı vardır: uzunluk ve başlangıç ​​noktası. Bu yüzden len () bir O (1), bilgisayar değeri saklar, bu yüzden sadece araması gerekir.


3

Python len () listenin büyüklüğüne bağlıdır düşünüyorum, bu yüzden her zaman birden çok kez kullanırsanız bir değişken uzunluğu saklamak. Ama bugün hata ayıklama sırasında, liste nesnesindeki __len__ özniteliğini fark ettim, bu yüzden len () sadece onu almalı, bu da O (1) karmaşıklığını yapar. Bu yüzden, birisi daha önce sordu ve bu gönderiye rastladıysa googled.


Ancak __len__bir işlevdir, bir listenin uzunluğunu temsil eden bir değişken değildir.
Kowalski

@Kowalski yes len bir işlevdir ama tek yaptığı şey
self.length

Fakat yayınınız bu konuda hiçbir şey söylemiyor. Ayrıca bu list.__len__fonksiyonun sabit zamanda çalıştığını nasıl anlarsınız ? Sadece bir fonksiyon olduğu için değil. Çünkü böyle uyguladı.
Kowalski
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.