74 votes

Pourquoi «range (0) == range (2, 2, 2)» est-il égal à True?

Pourquoi deux objets range différents initialisés avec une valeur différente se comparent-ils égaux dans Python 3? Lorsque j'exécute les commandes suivantes dans mon interpréteur:

 res = range(0) == range(2, 2, 2)
print(res)  # res = True
 

Le résultat imprimé est True . Pourquoi cela est-il ainsi? Pourquoi deux objets range différents avec des valeurs de paramètre différentes sont-ils traités de la même manière?

88voto

Jim Points 8793

L' range objets spéciaux:

Python comparer range objets comme des Séquences. Ce que cela signifie essentiellement, c'est que la comparaison n'est pas d'évaluer la façon dont ils représentent une séquence donnée, mais plutôt ce qu'ils représentent.

Le fait que l' start, stop et step paramètres sont complètement différents joue pas de différence ici, car ils représentent tous une liste vide, une fois dépliée:

Par exemple, la première range objet:

list(range(0))  # []

et le second range objet:

list(range(2, 2, 2)) # []

Les deux représentent une liste vide et depuis deux vide listes de comparer l'égalité (True) ainsi que l' range objets qui représentent eux.

Comme un résultat, vous pouvez avoir complètement différent à la recherche range objets; si elles représentent la même séquence, ils vont comparer l'égalité:

range(1, 5, 100) == range(1, 30, 100) 

Les deux représentent une liste avec un seul élément [1] de sorte que ces deux permettra également de comparer l'égalité.


Non, range des objets sont vraiment spécial:

Notez, cependant, que même si la comparaison n'est pas d'évaluer la façon dont ils représentent une séquence le résultat de la comparaison peut être réalisé en utilisant uniquement les valeurs de start, step avec l' len de la range objets; ce qui est très intéressant implications avec la vitesse de comparaisons:

r0 = range(1, 1000000)    
r1 = range(1, 1000000)

l0 = list(r0)    
l1 = list(r1)

Les plages compare super rapide:

%timeit r0 == r1
The slowest run took 28.82 times longer than the fastest. This could mean that an intermediate result is being cached 
10000000 loops, best of 3: 160 ns per loop

d'autre part, les listes..

%timeit l0 == l1
10 loops, best of 3: 27.8 ms per loop

Ouais..


Comme @SuperBiasedMan de noter que cela ne s'applique à la gamme d'objets en Python 3. Python 2 range() est une plaine ol' fonction qui retourne une liste, tandis que l' 2.x xrange objet n'est pas de la comparaison capabilies (et pas seulement ces..) qu' range des objets ont en Python 3.

Regarde @ajcr de réponse pour des devis directement à partir du code source sur Python 3 range objets. Il est documenté en ce que la comparaison entre les deux gammes différentes nécessite réellement: Simple rapide des opérations. L' range_equals fonction est utilisé dans l' range_richcompare fonction pour EQ et NE des cas et affectés à l' tp_richcompare membre pour PyRange_Type.

17voto

Jasper Points 1377

Citation directe à partir de la documentation (l'emphase est mienne):

Test de la gamme d'objets pour l'égalité avec les opérateurs == et != compare comme les séquences. C'est, deux objets sont égaux si ils représentent la même séquence de valeurs. (Notez que les deux objets que de comparer l'égalité pourraient avoir différents de démarrer, d'arrêter et d'étape attributs, par exemple range(0) == range(2, 1, 3) ou de la plage(0, 3, 2) == range(0, 4, 2).)

Si vous comparez ranges avec la "même" de la liste, vous obtiendrez de l'inégalité, comme indiqué dans les docs ainsi:

Les objets de différents types, à l'exception de différents types numériques, jamais comparer l'égalité.

Exemple:

>>> type(range(1))
<class 'range'>
>>> type([0])
<class 'list'>
>>> [0] == range(1)
False
>>> [0] == list(range(1))
True

Notez que cette explicitement ne s'applique qu'à Python 3. En Python 2, où range retourne une liste, range(1) == [0] évaluée True.

13voto

ajcr Points 4047

Pour ajouter un peu plus de détails pour les excellentes réponses sur cette page, deux range objets r0 et r1 sont comparés à peu près comme suit:

if r0 is r1:                 # True if r0 and r1 are same object in memory
    return True
if len(r0) != len(r1):       # False if different number of elements in sequences
    return False
if not len(r0):              # True if r0 has no elements
    return True
if r0.start != r1.start:     # False if r0 and r1 have different start values
    return False
if len(r0) == 1:             # True if r0 has just one element
    return True
return r0.step == r1.step    # if we made it this far, compare step of r0 and r1

La longueur d'un range objet est facile à calculer à l'aide de l' start, stop et step paramètres. Dans le cas où l' start == stop, par exemple, Python peut immédiatement savoir que la longueur est de 0. Dans non négligeable de cas, Python suffit de faire un simple calcul arithmétique à l'aide de l' start, stop et step valeurs.

Ainsi, dans le cas d' range(0) == range(2, 2, 2), Python est le suivant:

  1. voit qu' range(0) et range(2, 2, 2) sont des objets différents dans la mémoire.
  2. calcule la longueur de deux objets; les deux longueurs sont égales à 0 (car start == stop dans les deux objets) donc un autre test est nécessaire.
  3. voit qu' len(range(0)) est de 0. Cela signifie qu' len(range(2, 2, 2)) est également 0 (le test précédent pour l'inégalité d'échec), et de sorte que la comparaison doit renvoyer True.

7voto

George Zafiris Points 974

range(0) retours range(0,0). Vous démarrez à partir de 0 jusqu'à 0 à l'étape 1, qui n'est pas défini depuis le troisième argument ne peut pas être 0 [par défaut]. Vous ne pouvez pas atteindre 0 à 1. Pas de compteur d'action en place, donc 0.

range(2, 2, 2) retours range(2, 2, 2). Vous démarrez à partir de 2 jusqu'à 2 mais à l'étape 2. De nouveau, est fondamentalement 0 puisque vous n'avez pas compter jusqu'à quoi que ce soit.

range(0) == range(2,2,2) 

Vrai et exactement la même.

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