Bir listedeki öğelerin sayısını nasıl alabilirim?


1937

Aşağıdakileri göz önünde bulundur:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

# FAKE METHOD:
items.amount()  # Should return 3

Listedeki eleman sayısını nasıl alabilirim items?


23
Listedeki öğelerin sayısını açıkça soruyorsunuz. Bir araştırmacı buraya bellekteki nesnenin boyutunu aramaya gelirse, asıl soru ve aradıkları cevap budur: Python'da bir nesnenin boyutunu nasıl belirlerim?
Aaron Hall

Yanıtlar:


2640

len()Fonksiyon Python birkaç farklı türde kullanılabilir - hem yerleşik türleri ve kütüphane türleri. Örneğin:

>>> len([1,2,3])
3

Resmi 2.x belgeleri burada: Resmi 3.x belgeleri burada:len()
len()


239

Bir listenin boyutu nasıl alınır?

Bir listenin boyutunu bulmak için yerleşik işlevini kullanın len:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

Ve şimdi:

len(items)

3 döndürür.

açıklama

Python'daki her şey, listeler dahil olmak üzere bir nesnedir. Tüm nesnelerin C uygulamasında bir tür başlığı vardır.

Özellikle Python'da "boyutu" olan listeler ve diğer benzer yerleşik nesneler ob_size, nesnedeki öğelerin sayısının önbelleğe alındığı bir özniteliğe sahiptir . Dolayısıyla listedeki nesne sayısını kontrol etmek çok hızlıdır.

Ancak liste boyutunun sıfır olup olmadığını kontrol ediyorsanız, bunu kullanmayın len- bunun yerine listeyi bir boole bağlamına yerleştirin - boşsa Yanlış olarak kabul edilir, aksi takdirde True olarak kullanılır .

Gönderen docs

len(s)

Bir nesnenin uzunluğunu (öğe sayısı) döndürün. Argüman bir dizi (dize, bayt, demet, liste veya aralık gibi) veya bir koleksiyon (sözlük, küme veya dondurulmuş küme gibi) olabilir.

lenile uygulanan __len__veri modeli dan, docs :

object.__len__(self)

Yerleşik işlevi uygulamak için çağrılır len(). Nesnenin uzunluğunu döndürmeli, tamsayı> = 0 olmalıdır. Ayrıca, __nonzero__()[Python 2 veya __bool__()Python 3'te] yöntemini tanımlamayan ve __len__()yöntemi sıfır döndüren bir nesne Boole bağlamında yanlış kabul edilir.

Ve bunun __len__bir liste yöntemi olduğunu da görebiliriz :

items.__len__()

3 döndürür.

Yapabileceğiniz yerleşik tipler len(uzunluk)

Aslında, bu bilgiyi açıklanan tüm türler için alabileceğimizi görüyoruz:

>>> all(hasattr(cls, '__len__') for cls in (str, bytes, tuple, list, 
                                            xrange, dict, set, frozenset))
True

lenBoş veya boş bir listeyi test etmek için kullanmayın

Belirli bir uzunluğu test etmek için elbette eşitliği test edin:

if len(items) == required_length:
    ...

Ancak sıfır uzunluklu bir liste veya tersi için test etmek için özel bir durum vardır. Bu durumda, eşitliği test etmeyin.

Ayrıca, şunları yapmayın:

if len(items): 
    ...

Bunun yerine, şunları yapın:

if items:     # Then we have some items, not empty!
    ...

veya

if not items: # Then we have an empty list!
    ...

Ben niye burada açıklamak ancak Kısacası, if itemsya if not itemsikisi daha okunabilir ve daha performanslısı.


75

Bu, "kutunun dışında" işlevselliği olarak çok daha mantıklı olması nedeniyle yararlı olmasa da, oldukça basit bir kesmek, bir lengthözellikli bir sınıf oluşturmak olacaktır :

class slist(list):
    @property
    def length(self):
        return len(self)

Şöyle kullanabilirsiniz:

>>> l = slist(range(10))
>>> l.length
10
>>> print l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Temel olarak, OOP dostu bir lengthözelliğe sahip olmanın ek avantajı ile bir liste nesnesiyle tamamen aynıdır .

Her zaman olduğu gibi, kilometreniz değişebilir.


19
Bildiğiniz gibi, length = property(len)tek satırlık sarma işlevini atlayıp atlayabilir ve lenmülkünüzle ilgili belgeleri / içgörüleri koruyabilirsiniz .
Tadhg McDonald-Jensen

17

Ayrıca lenkullanabilirsiniz operator.length_hint(Python 3.4+ gerektirir). Normal için listher ikisi de eşdeğerdir, ancak length_hintbelirli durumlarda yararlı olabilecek bir liste yineleyicinin uzunluğunu almayı mümkün kılar:

>>> from operator import length_hint
>>> l = ["apple", "orange", "banana"]
>>> len(l)
3
>>> length_hint(l)
3

>>> list_iterator = iter(l)
>>> len(list_iterator)
TypeError: object of type 'list_iterator' has no len()
>>> length_hint(list_iterator)
3

Ancak length_hinttanım gereği sadece bir "ipucu" olduğundan, çoğu zaman lendaha iyidir.

Erişmeyi öneren birkaç yanıt gördüm __len__. Bu gibi yerleşik sınıflarla uğraşırken listsorun yoktur, ancak özel sınıflarla ilgili sorunlara yol açabilir, çünkü len(ve length_hint) bazı güvenlik kontrolleri uygular. Örneğin, her ikisi de belirli bir değeri ( sys.maxsizedeğeri) aşan negatif uzunluklara veya uzunluklara izin vermez . Bu nedenle yöntem lenyerine işlevi kullanmak her zaman daha güvenlidir __len__!


8

Sorunuzu daha önce verilen örnekler olarak cevaplamak:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

print items.__len__()

15
Python'da alt çizgilerle başlayan isimler semantik olarak herkese açık olmayan yöntemlerdir ve kullanıcılar tarafından kullanılmamalıdır.
Aaron Hall

2
1 __foo__.: Bu sadece bir kuraldır, Python sisteminin kullanıcı adlarıyla çakışmayan adları kullanmasının bir yoludur. 2 _foo.: Bu sadece bir kural, programcının değişkenin özel olduğunu (Python'da ne anlama gelirse) belirtmesinin bir yoludur. 3 __foo.: bunun gerçek bir anlamı vardır: tercüman _classname__foo, ismin başka bir sınıfta benzer bir isimle örtüşmemesini sağlamak için bu ismi değiştirir. * Python dünyasında başka hiçbir alt çizginin anlamı yoktur. * Bu sözleşmelerde sınıf, değişken, küresel vb. Arasında fark yoktur.
Shai Alon

4
Bu soru-cevap, özel yöntemleri neden doğrudan kullanıcı olarak kullanmamanız gerektiğini açıklar: stackoverflow.com/q/40272161/541136
Aaron Hall

@AaronHall ama len işlevi için neredeyse aynı. Çok büyük değişkenler için daha hızlı olabilir. Ancak, konuyu anlıyorum ve obj .__ len __ () yerine len (obj) kullanmalıyız.
Shai Alon

7

Ve bütünlük için (öncelikle eğitim amaçlı), len()işlevi kullanmadan mümkündür . Ben iyi bir seçenek olarak kabul edemeyeceği DO NOT PROGRAMI GİBİ BU İÇİNDE PYTHON ama algoritmaları öğrenmek için bir amaca hizmet eder.

def count(list):
    item_count = 0
    for item in list[:]:
        item_count += 1
    return item_count

count([1,2,3,4,5])

(İki nokta üst üste işareti list[:]örtüktür ve bu nedenle isteğe bağlıdır.)

Burada yeni programcılar için ders şöyledir: Bir listedeki öğelerin sayısını bir noktada saymadan alamazsınız. Soru şu: Onları saymak için iyi bir zaman ne zaman? Örneğin, bağlantı sistemi (C ile yazılmış) için bağlantı sistemi çağrısı gibi yüksek performanslı kod connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);, öğelerin uzunluğunu hesaplamaz (bu kodu arama koduna verir). Önce uzunluğu sayma adımını kaydetmek için adresin uzunluğunun geçtiğine dikkat edin? Başka bir seçenek: hesaplama olarak, ilettiğiniz nesne içine eklerken öğe sayısını takip etmek mantıklı olabilir. Bunun bellekte daha fazla yer kapladığını unutmayın. Bkz Naftuli Kay cevabı .

Bellekte daha fazla yer kaplarken performansı artırmak için uzunluğu takip etme örneği. Uzunluk izlendiğinden asla len () işlevini kullanmamam gerektiğini unutmayın:

class MyList(object):
    def __init__(self):
        self._data = []
        self.length = 0 # length tracker that takes up memory but makes length op O(1) time


        # the implicit iterator in a list class
    def __iter__(self):
        for elem in self._data:
            yield elem

    def add(self, elem):
        self._data.append(elem)
        self.length += 1

    def remove(self, elem):
        self._data.remove(elem)
        self.length -= 1

mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
print(mylist.length) # 3
mylist.remove(3)
print(mylist.length) # 2

Neden for item in list[:]:? Neden olmasın for item in list:? Ayrıca, += 1artırmak için kullanırdım .
Büyükanne Aching

@GrannyAching İsteğe bağlı iki nokta üst üste (aralık belirteci) açıkça bahsetmiştim. Menzil belirleyiciyi orada eğitim amaçlı bıraktım - ima edildiğini bilmek faydalıdır. Kodumla eşdeğer olarak önerdiğiniz gibi bir liste türü [] de çıkarılır. Artış operatörü ayrıca mevcut bir değişkene 1 eklemeye eşdeğerdir, ancak her durumda daha kısadır. Bu nedenle, bunun gerekçeniz ise kullanılması gerektiğine katılıyorum. Bu kod yine de hiçbir yerde üretilmemelidir (programlama öğrenimi hariç).
Jonathan Komar

0

Gerçekte nasıl len()çalıştığı açısından , bu C uygulamasıdır :

static PyObject *
builtin_len(PyObject *module, PyObject *obj)
/*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/
{
    Py_ssize_t res;

    res = PyObject_Size(obj);
    if (res < 0) {
        assert(PyErr_Occurred());
        return NULL;
    }
    return PyLong_FromSsize_t(res);
}

Py_ssize_tnesnenin sahip olabileceği maksimum uzunluktur. PyObject_Size()bir nesnenin boyutunu döndüren bir işlevdir. Bir nesnenin boyutunu belirleyemezse -1 döndürür. Bu durumda, bu kod bloğu yürütülür:

if (res < 0) {
        assert(PyErr_Occurred());
        return NULL;
    }

Ve sonuç olarak bir istisna ortaya çıkıyor. Aksi takdirde, bu kod bloğu yürütülür:

return PyLong_FromSsize_t(res);

resCtamsayı olan bir python'a dönüştürülür longve döndürülür. Tüm python tam sayıları longsPython 3'ten beri saklanır .


3
C uygulamasını bilmek veya bilmek neden önemlidir?
cs95

Bu soru CPython'a özgü olmadığından, bu cevap yanıltıcı olabilir. PyPy, IronPython, ... farklı uygulayabilir ve uygulayabilir.
MSeifert
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.