Esto es más una respuesta a Python 3.41 Un conjunto antes de que se cerrara como duplicado.
Los otros tienen razón: no confíe en el orden. Ni siquiera finjas que hay uno.
Dicho esto, hay una cosa en la que puede confiar:
list(myset) == list(myset)
Es decir, el orden es estable .
Comprender por qué hay un orden percibido requiere comprender algunas cosas:
Que Python usa conjuntos hash ,
Cómo se almacena el hash set de CPython en la memoria y
Cómo se numeran los números
Desde la parte superior:
Un conjunto de hash es un método para almacenar datos aleatorios con tiempos de búsqueda realmente rápidos.
Tiene una matriz de respaldo:
# A C array; items may be NULL,
# a pointer to an object, or a
# special dummy object
_ _ 4 _ _ 2 _ _ 6
Ignoraremos el objeto ficticio especial, que existe solo para hacer que las eliminaciones sean más fáciles de manejar, porque no eliminaremos de estos conjuntos.
Para tener una búsqueda realmente rápida, haces algo de magia para calcular un hash de un objeto. La única regla es que dos objetos que son iguales tienen el mismo hash. (Pero si dos objetos tienen el mismo hash, pueden ser desiguales).
Luego realiza un índice tomando el módulo por la longitud de la matriz:
hash(4) % len(storage) = index 2
Esto hace que sea realmente rápido acceder a elementos.
Hashes sólo son la mayor parte de la historia, como hash(n) % len(storage)
y hash(m) % len(storage)
pueden resultar en el mismo número. En ese caso, varias estrategias diferentes pueden intentar resolver el conflicto. CPython usa "sondeo lineal" 9 veces antes de hacer cosas complicadas, por lo que buscará a la izquierda de la ranura hasta 9 lugares antes de buscar en otro lado.
Los conjuntos de hash de CPython se almacenan así:
Un conjunto de hash no puede tener más de 2/3 de capacidad . Si hay 20 elementos y la matriz de respaldo tiene 30 elementos de largo, el almacén de respaldo cambiará de tamaño para ser más grande. Esto se debe a que se producen colisiones con mayor frecuencia en pequeñas tiendas de respaldo, y las colisiones ralentizan todo.
La tienda de respaldo cambia de tamaño en potencias de 4, comenzando en 8, excepto para conjuntos grandes (elementos de 50k) que cambian de tamaño en potencias de dos: (8, 32, 128, ...).
Por lo tanto, cuando crea una matriz, el almacén de respaldo es de longitud 8. Cuando está lleno 5 y agrega un elemento, contendrá brevemente 6 elementos. 6 > ²⁄₃·8
así que esto provoca un cambio de tamaño, y la tienda de respaldo se cuadruplica al tamaño 32.
Finalmente, hash(n)
solo devuelve los n
números (excepto -1
que es especial).
Entonces, veamos el primero:
v_set = {88,11,1,33,21,3,7,55,37,8}
len(v_set)
es 10, por lo que la tienda de respaldo es al menos 15 (+1) después de que se hayan agregado todos los artículos . El poder relevante de 2 es 32. Entonces, la tienda de respaldo es:
__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
Tenemos
hash(88) % 32 = 24
hash(11) % 32 = 11
hash(1) % 32 = 1
hash(33) % 32 = 1
hash(21) % 32 = 21
hash(3) % 32 = 3
hash(7) % 32 = 7
hash(55) % 32 = 23
hash(37) % 32 = 5
hash(8) % 32 = 8
así que estos se insertan como:
__ 1 __ 3 __ 37 __ 7 8 __ __ 11 __ __ __ __ __ __ __ __ __ 21 __ 55 88 __ __ __ __ __ __ __
33 ← Can't also be where 1 is;
either 1 or 33 has to move
Entonces esperaríamos una orden como
{[1 or 33], 3, 37, 7, 8, 11, 21, 55, 88}
con el 1 o 33 que no está al principio en otro lugar. Esto usará un sondeo lineal, por lo que tendremos:
↓
__ 1 33 3 __ 37 __ 7 8 __ __ 11 __ __ __ __ __ __ __ __ __ 21 __ 55 88 __ __ __ __ __ __ __
o
↓
__ 33 1 3 __ 37 __ 7 8 __ __ 11 __ __ __ __ __ __ __ __ __ 21 __ 55 88 __ __ __ __ __ __ __
Es posible que espere que el 33 sea el desplazado porque el 1 ya estaba allí, pero debido al cambio de tamaño que ocurre a medida que se construye el conjunto, este no es realmente el caso. Cada vez que se reconstruye el conjunto, los elementos ya agregados se reordenan de manera efectiva.
Ahora puedes ver por qué
{7,5,11,1,4,13,55,12,2,3,6,20,9,10}
Podría estar en orden. Hay 14 elementos, por lo que la tienda de respaldo es al menos 21 + 1, lo que significa 32:
__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
1 a 13 hash en los primeros 13 espacios. 20 va en la ranura 20.
__ 1 2 3 4 5 6 7 8 9 10 11 12 13 __ __ __ __ __ __ 20 __ __ __ __ __ __ __ __ __ __ __
55 va en la ranura hash(55) % 32
que es 23:
__ 1 2 3 4 5 6 7 8 9 10 11 12 13 __ __ __ __ __ __ 20 __ __ 55 __ __ __ __ __ __ __ __
Si elegimos 50 en su lugar, esperaríamos
__ 1 2 3 4 5 6 7 8 9 10 11 12 13 __ __ __ __ 50 __ 20 __ __ __ __ __ __ __ __ __ __ __
Y he aquí y he aquí:
{1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 20, 50}
#>>> {1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 50, 20}
pop
se implementa simplemente por el aspecto de las cosas: atraviesa la lista y aparece la primera.
Todo esto es detalle de implementación.