2012-08-10 18 views
10

tengo código como este:Cambiar el número de iteraciones de un bucle for

loopcount = 3 
for i in range(1, loopcount) 
    somestring = '7' 
    newcount = int(somestring) 
    loopcount = newcount 

así que lo que quiero es modificar el rango de la de 'dentro' del bucle.

Escribí este código esperando que el rango del bucle for cambie a (1,7) durante el primer bucle, pero no sucedió.

En su lugar, no importa qué número ingrese, solo se ejecuta 2 veces. (Quiero 6 veces .. en este caso)

he comprobado el valor utilizando la impresión como esto:

loopcount = 3 
    for i in range(1, loopcount) 
     print loopcount 
     somestring = '7' 
     newcount = int(somestring) 
     loopcount = newcount 
     print loopcount 
#output: 
3 
7 
7 
7 

Cuál es el problema? el numero ha sido cambiado

¿Dónde está mi pensamiento equivocado?

+0

Sí, es posible cambiar el rango desde el interior del bucle, ver la nueva respuesta a continuación. –

Respuesta

23

La gama se crea basándose en el valor de loopcount en el momento que se llama - todo lo que sucede después es que LoopCount irrelevante. Lo que probablemente quiere es una sentencia while:

loopcount = 3 
i = 1 
while i < loopcount: 
    somestring = '7' 
    loopcount = int(somestring) 
    i += 1 

Los while pruebas de que la condición i < loopcount es cierto, y si es cierto, si ejecuta las sentencias que contiene. En este caso, en cada pasada a través del bucle, i se incrementa en 1. Dado que el recuento de bucles se establece en 7 en la primera vez, el bucle se ejecutará seis veces, para i = 1,2,3,4,5 y 6

Una vez que la condición es falsa, cuando i = 7, el ciclo while deja de funcionar.

(No sé cuál es tu caso de uso real, pero puede que no necesites asignar una nueva cuenta, así que lo eliminé).

+2

El tiempo probablemente debería terminar con 'i + = 1' para simular el incremento automático al iterar sobre un rango –

+0

Gracias. Ha cambiado ahora. –

+0

my for tiene muchos códigos dentro de él ¿no tendría ningún cambio en los resultados si uso while y i + = 1? –

9

Desde el range() docstring:

rango ([Inicio], detener [, incremento]) -> lista de enteros

devolver una lista que contiene una progresión aritmética de números enteros. rango (i, j) devuelve [i, i + 1, i + 2, ..., j-1]; start (!) se establece de manera predeterminada en 0. Cuando se da un paso, especifica el incremento (o decremento). Por ejemplo, el rango (4) devuelve [0, 1, 2, 3]. ¡El punto final se omite! Estos son exactamente los índices válidos para una lista de 4 elementos.

Así, range(1, 10), por ejemplo, devuelve una lista como: [1,2,3,4,5,6,7,8,9], así, su código es básicamente haciendo:

loopcount = 3 
for i in [1, 2]: 
    somestring = '7' 
    newcount = int(somestring) 
    loopcount = newcount 

Cuando el bucle for se "inicializa", la lista es creada por range() .

+0

aha! ¡entiendo! pero ¿cómo cambio el rango 'dentro' del ciclo? no puedo hacerlo? –

+2

Si necesita modificar los límites de su bucle, le sugiero que lo codifique con un 'while', como lo sugiere @ user802500. –

1

Cuando se evalúa la función range() en el for -loop, genera una secuencia de valores (es decir, una lista) que se utilizará para iterar.

range() utiliza el valor de loopcount para esto. Sin embargo, vez esa secuencia se ha generado, nada de lo que dentro el bucle cambiará esa lista, es decir, incluso si cambia loopcount más tarde, la lista original se mantendrá igual => el número de iteraciones se mantendrá igual .

En su caso:

loopcount = 3 
for i in range(1, loopcount): 

convierte

for i in [1, 2]: 

por lo que su bucle itera dos veces, ya que tiene 2 print declaraciones en el bucle de tu escapada de 4 líneas de salida. Tenga en cuenta que está imprimiendo el valor de loopcount que inicialmente es 3, pero luego se establece (y reinicia) en 7.

Si desea poder cambiar dinámicamente el número de iteración, considere utilizar un enlace while. Por supuesto, siempre puede detener/salir de cualquier bucle anticipadamente con el uso de la instrucción break.

Además,

somestring = '7' 
    newcount = int(somestring) 

se puede simplificar a solo

newcount = 7 
1

Parece que su premisa es que tiene un número predeterminado de veces que se debe ejecutar el ciclo, pero una condición ocasional en la que es diferente. Puede ser que sea mejor utilizar un bucle while en lugar, pero sin tener en cuenta que sólo se puede hacer:

if i == some_calculated_threshold: 
    break 

a caer fuera del circuito en su lugar.

+1

-1; la pregunta original está tratando de aumentar el número de veces a través del ciclo de 2 a 7; ¿Cómo se supone que 'break' ayuda? – geoffspear

0

Puede no aumento del número de iteraciones vez que se ha establecido el rango, pero se puede romper antes de tiempo, lo que disminuye el número de iteraciones:

for i in xrange(1, 7): 
    if i == 2: 
     break 
2

para tratar específicamente la pregunta "¿Cómo Cómo puedo cambiar los límites de rango", puede aprovechar la send method for a generator:

def adjustable_range(start, stop=None, step=None): 
    if stop is None: 
     start, stop = 0, start 

    if step is None: step = 1 

    i = start 
    while i < stop: 
     change_bound = (yield i) 
     if change_bound is None: 
      i += step 
     else: 
      stop = change_bound 

Uso:

myrange = adjustable_range(10) 

for i in myrange: 
    if some_condition: 
     myrange.send(20) #generator is now bounded at 20 
+2

+1, aunque esta no es una expresión de generador * - solo un generador. – lvc

+0

@lvc: Vaya, editado. –

+0

Es posible que desee intentar ejecutar su código. Intenté arreglar tu versión con otra publicada en esta página. –

0

Aquí hay una implementación más completa de la función adjustable_range proporcionada por Joel Cornett.

def adjustable_range(start, stop=None, step=None): 
    if not isinstance(start, int): 
     raise TypeError('start') 
    if stop is None: 
     start, stop = 0, start 
    elif not isinstance(stop, int): 
     raise TypeError('stop') 
    direction = stop - start 
    positive, negative = direction > 0, direction < 0 
    if step is None: 
     step = +1 if positive else -1 
    else: 
     if not isinstance(step, int): 
      raise TypeError('step') 
     if positive and step < 0 or negative and step > 0: 
      raise ValueError('step') 
    if direction: 
     valid = (lambda a, b: a < b) if positive else (lambda a, b: a > b) 
     while valid(start, stop): 
      message = yield start 
      if message is not None: 
       if not isinstance(message, int): 
        raise ValueError('message') 
       stop = message 
      start += step 
3

El bucle while respuesta dada por user802500 es probable que sea la mejor solución a su problema real; sin embargo, creo que la pregunta como se le preguntó tiene una respuesta interesante e instructiva.

El resultado de la llamada al () es una lista de valores consecutivos. For-loop itera sobre esa lista hasta que se agote.

Aquí está el punto clave: Puede cambiar la lista durante la iteración.

>>> loopcount = 3 
>>> r = range(1, loopcount) 
>>> for i in r: 
     somestring = '7' 
     newcount = int(somestring) 
     del r[newcount:] 

Un uso práctico de esta función está interactuando sobre tareas en una lista de tareas y permitiendo algunas tareas para generar nuevos Todos:

for task in tasklist: 
    newtask = do(task) 
    if newtask: 
     tasklist.append(newtask) 
+0

Buen truco de usar ser mutable para la lista. Entonces, supongo que en la situación en que la nueva cuenta es más grande que el tamaño de la lista original, en lugar de usar 'del' para eliminar algunos elementos del rango, usaríamos 'append'. – ntough

Cuestiones relacionadas