114 votes

Y a-t-il un besoin de range(len(a))?

On trouve fréquemment des expressions de ce type dans les questions python sur SO. Que ce soit pour accéder à tous les éléments de l'itérable

for i in range(len(a)):
    print(a[i])

Ce qui est simplement une façon maladroite d'écrire:

for e in a:
    print(e)

Ou pour assigner des éléments de l'itérable:

for i in range(len(a)):
    a[i] = a[i] * 2

Ce qui devrait être le même que:

for i, e in enumerate(a):
     a[i] = e * 2
# Ou si ce n'est pas trop coûteux de créer un nouvel itérable
a = [e * 2 for e in a]

Ou pour filtrer sur les indices:

for i in range(len(a)):
    if i % 2 == 1: continue
    print(a[i])

Ce qui pourrait être exprimé comme ceci:

for e in a [::2]:
    print(e)

Ou lorsque vous avez juste besoin de la longueur de la liste, et pas de son contenu:

for _ in range(len(a)):
    faireQuelqueChoseNonLiéA()

Ce qui pourrait être:

for _ in a:
    faireQuelqueChoseNonLiéA()

En python nous avons enumerate, le slicing, filter, sorted, etc... Comme les constructions for en python sont destinées à itérer sur des itérables et non seulement des plages d'entiers, y a-t-il des cas d'utilisation réels où vous avez besoin de in range(len(a))?

19voto

Jon Clements Points 51556

Si vous avez besoin de travailler avec des indices d'une séquence, alors oui - vous l'utilisez... par exemple pour l'équivalent de numpy.argsort...:

>>> a = [6, 3, 1, 2, 5, 4]
>>> sorted(range(len(a)), key=a.__getitem__)
[2, 3, 1, 5, 4, 0]

13voto

Erik Allik Points 9158

Réponse courte: mathématiquement parlant, non, en termes pratiques, oui, par exemple pour la programmation intentionnelle.

Techniquement, la réponse serait "non, ce n'est pas nécessaire" car c'est exprimable en utilisant d'autres structures. Mais en pratique, j'utilise for i in range(len(a) (ou for _ in range(len(a)) si je n'ai pas besoin de l'index) pour indiquer explicitement que je veux itérer autant de fois qu'il y a d'éléments dans une séquence sans avoir besoin d'utiliser les éléments de la séquence pour quelque chose.

Donc: "Est-ce nécessaire?" — oui, j'en ai besoin pour exprimer la signification/l'intention du code à des fins de lisibilité.

Voir aussi: https://en.wikipedia.org/wiki/Intentional_programming

Et évidemment, s'il n'y a pas de collection associée à l'itération du tout, for ... in range(len(N)) est la seule option, afin de ne pas recourir à i = 0; while i < N; i += 1 ...

11voto

Giswok Points 521

Et si vous avez besoin d'accéder simultanément à deux éléments de la liste ?

for i in range(len(a[0:-1])):
    something_new[i] = a[i] * a[i+1]

Vous pouvez utiliser ceci, mais c'est probablement moins clair :

for i, _ in enumerate(a[0:-1]):
     something_new[i] = a[i] * a[i+1]

Personnellement, je ne suis pas à 100% satisfait de l'un ou l'autre !

2voto

En se basant sur les commentaires ainsi que sur mon expérience personnelle, je dirais non, il n'y a pas besoin de range(len(a)). Tout ce que vous pouvez faire avec range(len(a)) peut être fait d'une autre manière (généralement beaucoup plus efficace).

Vous avez donné de nombreux exemples dans votre message, donc je ne vais pas les répéter ici. Au lieu de cela, je vais donner un exemple pour ceux qui disent "Et si je veux juste la longueur de a, pas les éléments?". C'est l'une des seules fois où vous pourriez envisager d'utiliser range(len(a)). Cependant, même cela peut être fait de la manière suivante:

>>> a = [1, 2, 3, 4]
>>> for _ in a:
...     print True
...
True
True
True
True
>>>

La réponse de Clements (comme le montre Allik) peut également être retravaillée pour supprimer range(len(a)):

>>> a = [6, 3, 1, 2, 5, 4]
>>> sorted(range(len(a)), key=a.__getitem__)
[2, 3, 1, 5, 4, 0]
>>> # Notez cependant que, dans ce cas, range(len(a)) est plus efficace.
>>> [x for x, _ in sorted(enumerate(a), key=lambda i: i[1])]
[2, 3, 1, 5, 4, 0]
>>>

En conclusion, range(len(a)) n'est pas nécessaire. Son seul avantage est la lisibilité (son intention est claire). Mais ce n'est qu'une question de préférence et de style de code.

2voto

Parfois, matplotlib nécessite range(len(y)), par exemple, alors que y=array([1,2,5,6]), plot(y) fonctionne bien, scatter(y) ne fonctionne pas. Il faut écrire scatter(range(len(y)),y). (Personnellement, je pense qu'il s'agit d'un bogue dans scatter; plot et ses amis scatter et stem devraient utiliser les mêmes séquences d'appel autant que possible.)

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