Comment obtenir le nombre d'éléments dans une liste?

1938

Considérer ce qui suit:

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

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

Comment obtenir le nombre d'éléments dans la liste items?

y2k
la source
23
Vous demandez évidemment le nombre d'éléments dans la liste. Si un chercheur vient ici à la recherche de la taille de l'objet en mémoire, voici la vraie question et les réponses qu'il recherche: comment déterminer la taille d'un objet en Python?
Aaron Hall

Réponses:

2640

La len()fonction peut être utilisée avec plusieurs types différents en Python - à la fois des types intégrés et des types de bibliothèque. Par exemple:

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

La documentation officielle 2.x est ici: La documentation officielle 3.x est ici:len()
len()

gnud
la source
239

Comment obtenir la taille d'une liste?

Pour trouver la taille d'une liste, utilisez la fonction de commande intégrée, len:

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

Et maintenant:

len(items)

renvoie 3.

Explication

Tout en Python est un objet, y compris les listes. Tous les objets ont un en-tête dans l'implémentation C.

Les listes et autres objets intégrés similaires avec une "taille" en Python, en particulier, ont un attribut appelé ob_size, où le nombre d'éléments dans l'objet est mis en cache. Il est donc très rapide de vérifier le nombre d'objets dans une liste.

Mais si vous vérifiez si la taille de la liste est nulle ou non, n'utilisez pas len- placez plutôt la liste dans un contexte booléen - elle est traitée comme Faux si vide, Vrai sinon .

À partir des documents

len(s)

Renvoie la longueur (le nombre d'articles) d'un objet. L'argument peut être une séquence (telle qu'une chaîne, des octets, un tuple, une liste ou une plage) ou une collection (telle qu'un dictionnaire, un ensemble ou un ensemble figé).

lenest implémenté avec __len__, à partir des documents du modèle de données :

object.__len__(self)

Appelé pour implémenter la fonction intégrée len(). Doit renvoyer la longueur de l'objet, un entier> = 0. De plus, un objet qui ne définit pas de méthode __nonzero__()[en Python 2 ou __bool__()en Python 3] et dont la __len__()méthode retourne zéro est considéré comme faux dans un contexte booléen.

Et nous pouvons également voir que __len__c'est une méthode de listes:

items.__len__()

renvoie 3.

Types intégrés, vous pouvez obtenir la len(longueur) de

Et en fait, nous voyons que nous pouvons obtenir ces informations pour tous les types décrits:

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

Ne pas utiliser lenpour tester une liste vide ou non vide

Pour tester une longueur spécifique, bien sûr, testez simplement l'égalité:

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

Mais il existe un cas particulier pour tester une liste de longueur nulle ou l'inverse. Dans ce cas, ne testez pas l'égalité.

Aussi, ne faites pas:

if len(items): 
    ...

Au lieu de cela, faites simplement:

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

ou

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

J'explique pourquoi ici mais en bref, if itemsou if not itemsest à la fois plus lisible et plus performant.

Aaron Hall
la source
75

Bien que cela puisse ne pas être utile en raison du fait que cela aurait beaucoup plus de sens d'être une fonctionnalité "prête à l'emploi", un hack assez simple serait de construire une classe avec une lengthpropriété:

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

Vous pouvez l'utiliser comme ceci:

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

Essentiellement, il est exactement identique à un objet liste, avec l'avantage supplémentaire d'avoir un OOP-friendly length propriété .

Comme toujours, votre kilométrage peut varier.

Naftuli Kay
la source
19
juste pour que vous sachiez, vous pouvez simplement faire length = property(len)et ignorer la fonction d'encapsuleur d'une ligne et conserver la documentation / introspection de lenvotre propriété.
Tadhg McDonald-Jensen
17

En outre, lenvous pouvez également utiliser operator.length_hint(nécessite Python 3.4+). Pour un normal les listdeux sont équivalents, mais length_hintpermet d'obtenir la longueur d'un list-iterator, ce qui pourrait être utile dans certaines circonstances:

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

Mais length_hintn'est par définition qu'un "indice", donc la plupart du temps lenc'est mieux.

J'ai vu plusieurs réponses suggérant l'accès __len__. C'est bien quand il s'agit de classes intégrées comme list, mais cela pourrait entraîner des problèmes avec les classes personnalisées, car len(et length_hint) implémenter des contrôles de sécurité. Par exemple, les deux n'autorisent pas les longueurs négatives ou les longueurs qui dépassent une certaine valeur (la sys.maxsizevaleur). Il est donc toujours plus sûr d'utiliser la lenfonction au lieu de la __len__méthode!

MSeifert
la source
8

Répondre à votre question comme les exemples également donnés précédemment:

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

print items.__len__()
Shai Alon
la source
15
En Python, les noms commençant par des traits de soulignement sont des méthodes sémantiquement non publiques et ne doivent pas être utilisées par les utilisateurs.
Aaron Hall
2
1 __foo__.: c'est juste une convention, un moyen pour le système Python d'utiliser des noms qui n'entreront pas en conflit avec les noms d'utilisateurs. 2 _foo.: c'est juste une convention, une façon pour le programmeur d'indiquer que la variable est privée (quoi que cela signifie en Python). 3 __foo.: cela a une signification réelle: l'interpréteur remplace ce nom par _classname__foocomme un moyen de s'assurer que le nom ne chevauchera pas avec un nom similaire dans une autre classe. * Aucune autre forme de soulignement n'a de sens dans le monde Python. * Il n'y a aucune différence entre classe, variable, global, etc. dans ces conventions.
Shai Alon
4
Ce Q&R explique pourquoi vous ne devriez pas utiliser les méthodes spéciales directement en tant qu'utilisateur: stackoverflow.com/q/40272161/541136
Aaron Hall
@AaronHall mais pour la fonction len c'est presque la même chose. Cela pourrait être plus rapide pour les très grandes variables. Cependant, je comprends votre point de vue et nous devrions utiliser len (obj) et non obj .__ len __ ().
Shai Alon
7

Et pour être complet (principalement pédagogique), c'est possible sans utiliser la len()fonction. Je ne tolérerais pas cela comme une bonne option NE PAS PROGRAMMER COMME CECI EN PYTHON , mais cela sert à l'apprentissage des algorithmes.

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

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

(Le signe deux-points list[:]est implicite et est donc également facultatif.)

La leçon ici pour les nouveaux programmeurs est: vous ne pouvez pas obtenir le nombre d'éléments dans une liste sans les compter à un moment donné. La question devient: quel est le bon moment pour les compter? Par exemple, un code hautes performances comme l'appel système de connexion pour les sockets (écrit en C) connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);, ne calcule pas la longueur des éléments (donnant cette responsabilité au code appelant). Notez que la longueur de l'adresse est transmise pour enregistrer l'étape de comptage de la longueur en premier? Autre option: sur le plan du calcul, il peut être judicieux de garder une trace du nombre d'éléments lorsque vous les ajoutez dans l'objet que vous passez. N'oubliez pas que cela prend plus de place dans la mémoire. Voir la réponse de Naftuli Kay .

Exemple de suivi de la longueur pour améliorer les performances tout en occupant plus d'espace en mémoire. Notez que je n'utilise jamais la fonction len () car la longueur est suivie:

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
Jonathan Komar
la source
Pourquoi for item in list[:]:? Pourquoi ne pas for item in list:? Aussi, j'utiliserais += 1pour incrémenter.
Granny Aching
@GrannyAching J'ai explicitement mentionné les deux points facultatifs (spécificateur de plage). J'ai laissé le spécificateur de plage à des fins éducatives - il est avantageux de savoir que cela est implicite. Un type de liste [] est également déduit, comme vous le suggérez, équivalent à mon code. L'opérateur d'incrément équivaut également à ajouter 1 à une variable existante, mais plus court dans tous les cas. Je suis donc d'accord pour qu'il soit utilisé si tel est votre raisonnement. Ce code ne doit pas être mis en production n'importe où, de toute façon (sauf lors de l'apprentissage de la programmation).
Jonathan Komar
0

En termes de len()fonctionnement, voici son implémentation C :

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_test la longueur maximale que l'objet peut avoir. PyObject_Size()est une fonction qui renvoie la taille d'un objet. S'il ne peut pas déterminer la taille d'un objet, il renvoie -1. Dans ce cas, ce bloc de code sera exécuté:

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

Et une exception est levée en conséquence. Sinon, ce bloc de code sera exécuté:

return PyLong_FromSsize_t(res);

resqui est un Centier, est converti en python longet renvoyé. Tous les entiers python sont stockés comme longsdepuis Python 3.

Alec Alameddine
la source
3
Pourquoi est-il important de connaître ou de connaître l'implémentation C
cs95
Étant donné que cette question n'est pas spécifique à CPython, cette réponse peut être trompeuse. PyPy, IronPython, ... peuvent et implémentent différemment.
MSeifert
0

Ici, vous voulez la longueur de la liste, utilisez donc la simple fonction len () pour le calcul.

A=[1,2,3,4,5]
print(len(A))
Umesh Yadav
la source