Pregunta Bucles infinitos usando 'for' en Python [duplicado]


Esta pregunta ya tiene una respuesta aquí:

¿Por qué esto no crea un ciclo infinito?

a=5
for i in range(1,a):
  print(i)
  a=a+1

o esto

for i in range(1,4):
  print(i)
  i=i-1

o esto

for i in range(1,4):
  print(i)
  i=1

¿Hay alguna manera de que podamos crear bucles infinitos utilizando una for ¿lazo? Sé que está el while para eso, pero solo tenía curiosidad.


5
2018-01-11 11:53


origen


Respuestas:


range es un clase, y usar en como por ejemplo range(1, a) crea un objeto de esa clase. Este objeto es creado solamente una vez, no se recrean cada iteración del bucle. Esa es la razón por la que el primer ejemplo no dará como resultado un bucle infinito.

Los otros dos bucles no son infinitos porque, a diferencia de los range objeto, la variable de bucle i  es recreado (o más bien reinicializado) cada iteración. Los valores que asigne a i dentro del bucle se sobrescribirá a medida que el bucle se repita.


5
2018-01-11 12:00



Considera un for lazo:

for item in iterable:
    print(item)

La idea es que siempre y cuando iterable no ha cambiado, recorreremos todos y cada uno item dentro iterable una vez. Por ejemplo,

for item in [3, 2, 1, 666]:
    print(item)

saldrá 3 2 1 666. En particular, encontramos que range(1, 4) Es una forma fácil de representar un iterable. [1, 2, 3]. Así,

for i in range(1, 4):
    print(i)

saldrá 1 2 3.


Ejemplo 1

a=5
for i in range(1,a):
  print(i)
  a=a+1

En este caso, range(1,a) es evaluado una vez, cuando comienza el bucle.

Ejemplo 2

for i in range(1,4):
  print(i)
  i=i-1

En este caso, i Se reevalúa cada bucle, antes de ejecutar el print y i=i-1 declaraciones dentro del cuerpo del bucle.

Ejemplo 3

for i in range(1,4):
  print(i)
  i=1

Al igual que Ejemplo 2, i Se reevalúa cada bucle.


3
2018-01-11 11:59



No puede, en este caso, actualizar el iterador que su for bucle está en bucle sobre.


los range en for i in range(a): es en realidad una función: toma un valor, a, y devuelve un objeto que contiene los valores por los que pasará. Una vez que haya creado ese objeto, puede cambiar la variable de entrada todo lo que desee, y ese objeto no cambiará.

Imagina si hiciéramos nuestra propia función similar llamada my_range que genera una lista (mientras que el construido en range la función genera un range)

def my_range(end):
    my_list = []
    for i in range(end):
        my_list.append(i)
    return my_list

Ahora si tuviéramos que usar nuestra nueva función, así:

a = 4
for i in my_range(a):
    print(i)
    a += 1

Sería obvio que no podemos actualizar el objeto de la lista que estamos haciendo un bucle cambiando a, porque la lista que estamos revisando ya se ha hecho, y no se está rehaciendo en cada ciclo.


¿Puedes hacer un bucle infinito en python? Sí, simplemente agregue una nueva entrada al objeto por el que está pasando, por ejemplo:

my_list = [0]
for i in my_list:
    print(i)
    my_list.append(i+1)

Ahora estamos actualizando el objeto sobre el que estamos en bucle.


3
2018-01-11 12:10



Debido a que un rango es una lista (Python2) o un range objeto ambos de los cuales son finitos. Ese rango se crea una vez antes de que comience el bucle. A la variable de bucle se le asigna el siguiente elemento del rango al comienzo de cada iteración, independientemente de lo que le asigne más adelante en el cuerpo del bucle. Necesitas un iterador infinito para un bucle infinito, por ej. itertools.cycle:

from itertools import cycle
for x in cycle(range(5)):
    # endless

1
2018-01-11 12:05



for bucles y la range(..) objeto

Si tú escribes for i in range(..): Python lo hace no traducir esto en algo así como for(int i = 0; i < n; i++) (en la familia del lenguaje de programación C).

Además, el objeto de rango se construye una vez, antes de la for lazo. los range(..) Objeto, no sabe qué variables se han utilizado para construirlo. Una vez construido, el rango es fijo.

Ve range(..) como un iterable objeto, y cada iteración, toma el siguiente elemento de los rendimientos iterables. Así que si configura la variable o no en el for lazo, tiene no Efecto para la siguiente iteración.

En , range(..) no es un objeto específico, sino una llamada para construir una lista. Entonces si llamas range(10) (sin el for bucle), obtienes [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].

¿Por qué no funciona?

Entonces, ¿por qué los ejemplos no funcionan?

a=5
for i in range(1,a):
  print(i)
  a=a+1

Aquí construimos range(..) una vez. Después de eso, las variables basadas en las cuales fue construido pueden cambiar, ya que el range(..) El objeto ya cambia. Incrementando a por lo tanto, no significará range el objeto se hará más grande

for i in range(1,4):
  print(i)
  i=i-1

los for bucle cada vez toma el siguiente Ítem ​​de lo iterable. Entonces, si primero hemos recolectado 1 desde el range bucle, la siguiente iteración, recogemos 2. Esto es independientemente de lo que el valor de i es.

for i in range(1,4):
  print(i)
  i=1

Por la misma razón: for hace no tener en cuenta el valor anterior de i. Solo recupera el siguiente elemento lo iterable (aquí range(..) rendimientos). Ya que range(..) es fijo, simplemente alimentará el for bucle el siguiente elemento.

Emulando un bucle infinito

Entonces, necesitamos construir un iterable que siga arrojando elementos. Una forma de hacer esto es itertools.count:

from itertools import count

for i in count():
    # ...
    pass

O si no está interesado en algún valor, podemos usar repeat también:

from itertools import repeat

for _ in repeat(None):
    # ...
    pass

1
2018-01-11 12:02



range Copia los parámetros que se le dan para uso interno. Así que los cambios a los posteriores no tienen efecto. Lo mismo que con la variable de bucle, que solo se crea a partir de los valores internos cada vez.

Eso es diferente aunque si usas un objeto mutable como un list para iterar sobre:

a = [1,2,3]

for i in a:
    a.append(i)

Este bucle se ejecutará infinitamente.


1
2018-01-11 12:06