85 votes

Existe-t-il une méthode intégrée pour obtenir la longueur d'un itérable en Python ?

Par exemple, les fichiers, en Python, sont itérables - ils itèrent sur les lignes du fichier. Je veux compter le nombre de lignes.

Voici un moyen rapide d'y parvenir :

lines = len(list(open(fname)))

Cependant, cette opération charge tout le fichier en mémoire (en une seule fois). Cela va à l'encontre de l'objectif d'un itérateur (qui ne doit conserver que la ligne courante en mémoire).

Cela ne fonctionne pas :

lines = len(line for line in open(fname))

car les générateurs n'ont pas de longueur.

Existe-t-il un moyen d'y parvenir sans définir une fonction de comptage ?

def count(i):
    c = 0
    for el in i: c += 1
    return c

Pour clarifier, je comprends que le fichier entier devra être lu ! C'est juste que je ne veux pas qu'il soit en mémoire en une seule fois.

95voto

Kamil Kisiel Points 7298

À moins d'itérer à travers l'itérable et de compter le nombre d'itérations, non. C'est ce qui en fait un itérable et non une liste. Ce n'est même pas un problème spécifique à Python. Regardez la structure de données classique des listes chaînées. Trouver la longueur est une opération O(n) qui implique d'itérer toute la liste pour trouver le nombre d'éléments.

Comme mcrute l'a mentionné plus haut, vous pouvez probablement réduire votre fonction à :

def count_iterable(i):
    return sum(1 for e in i)

Bien sûr, si vous définissez votre propre objet itérable, vous pouvez toujours implémenter __len__ et conservez un décompte des éléments quelque part.

25voto

Bodhi Points 19

Si vous avez besoin d'un nombre de lignes, vous pouvez le faire, je ne connais pas de meilleur moyen :

line_count = sum(1 for line in open("yourfile.txt"))

17voto

wouter bolsterlee Points 1873

En cardinality fournit une solution efficace de count() et quelques fonctions apparentées pour compter et vérifier la taille d'un itérable : http://cardinality.readthedocs.org/

import cardinality

it = some_iterable(...)
print(cardinality.count(it))

En interne, il utilise enumerate() y collections.deque() de déplacer toute la logique de bouclage et de comptage au niveau C, ce qui a permis d'accélérer considérablement le processus par rapport à la logique de comptage et de bouclage. for en Python.

12voto

ttepasse Points 372

J'utilise cette redéfinition depuis un certain temps déjà :

def len(thingy):
    try:
        return thingy.__len__()
    except AttributeError:
        return sum(1 for item in iter(thingy))

11voto

pylang Points 12013

Il s'avère qu'il existe une solution mise en œuvre pour cela problème courant . Envisagez d'utiliser le ilen() de la fonction more_itertools .

more_itertools.ilen(iterable)

Un exemple d'impression d'un nombre de lignes dans un fichier (nous utilisons la fonction with pour gérer en toute sécurité la fermeture des fichiers) :

# Example
import more_itertools

with open("foo.py", "r+") as f:
    print(more_itertools.ilen(f))

# Output: 433

Cet exemple donne le même résultat que les solutions présentées précédemment pour totaliser les lignes d'un fichier :

# Equivalent code
with open("foo.py", "r+") as f:
    print(sum(1 for line in f))

# Output: 433

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X