¿Es posible hacer un bucle `for` sin una variable iteradora? (¿Cómo puedo hacer que el código se repita un número determinado de veces?)

7 minutos de lectura

¿Es posible hacer el seguimiento sin el i?

for i in range(some_number):
    # do something

Si solo quiere hacer algo N cantidad de veces y no necesita el iterador.

  • ¡Esta es una buena pregunta! PyDev incluso marca la ‘i’ como una advertencia de ‘variable no utilizada’. La solución a continuación elimina esta advertencia.

    –Ashwin Nanjappa

    16 de noviembre de 2009 a las 10:26

  • @Ashwin Puede usar \@UnusedVariable para eliminar esa advertencia. Tenga en cuenta que necesitaba escapar del símbolo ‘arroba’ para que este comentario pasara.

    – khatchad

    24 de octubre de 2011 a las 4:17


  • Te hago la misma pregunta. Es molesto con las advertencias de pylint. Por supuesto, puede desactivar las advertencias mediante supresión adicional como propuso @Raffi Khatchadourian. Sería bueno evitar las advertencias de pylint. y comentarios de supresión.

    – tangoal

    14 de febrero de 2020 a las 15:30

Fuera de mi cabeza, no.

Creo que lo mejor que podrías hacer es algo como esto:

def loop(f,n):
    for i in xrange(n): f()

loop(lambda: <insert expression here>, 5)

Pero creo que puedes vivir con el extra i variable.

Aquí está la opción de usar el _ variable, que en realidad es una variable más.

for _ in range(n):
    do_something()

Tenga en cuenta que _ se le asigna el último resultado que se devolvió en una sesión interactiva de python:

>>> 1+2
3
>>> _
3

Por esta razón, no lo usaría de esta manera. No conozco ningún idioma mencionado por Ryan. Puede estropear su intérprete.

>>> for _ in xrange(10): pass
...
>>> _
9
>>> 1+2
3
>>> _
9

y de acuerdo a Gramática de Pythones un nombre de variable aceptable:

identifier ::= (letter|"_") (letter | digit | "_")*

  • “Pero creo que puedes vivir con la “i” adicional” Sí, es solo un punto académico.

    –James McMahon

    4 de mayo de 2009 a las 5:16

  • @nemo, puede intentar hacerlo por _ en el rango (n): si no desea usar nombres alfanuméricos.

    – Desconocido

    4 de mayo de 2009 a las 5:19

  • @nemo Sí, es solo un nombre de variable aceptable. En el intérprete, se le asigna automáticamente la última expresión que hizo.

    – Desconocido

    4 de mayo de 2009 a las 5:24

  • @kurczak Hay un punto. Usando _ deja en claro que debe ser ignorado. Decir que no tiene sentido hacer esto es como decir que no tiene sentido comentar tu código, porque de todos modos haría exactamente lo mismo.

    – Hada Lambda

    2 de enero de 2012 a las 3:37


  • Otra buena razón para _ en lugar de i es que parece que pylint (y quizás otros linters) leerán _ como un descarte y no dar una advertencia de variable no utilizada.

    –Cameron Bielstein

    23 de abril de 2019 a las 6:34

usted puede estar buscando

for _ in itertools.repeat(None, times): ...

esta es LA forma más rápida de iterar times veces en Python.

  • No me preocupaba el rendimiento, solo tenía curiosidad por saber si había una forma más breve de escribir la declaración. Si bien he estado usando Python esporádicamente durante aproximadamente 2 años, todavía siento que me falta mucho. Itertools es una de esas cosas, gracias por la información.

    –James McMahon

    4 de mayo de 2009 a las 5:56

  • Que interesante, no lo sabía. Acabo de echar un vistazo a los documentos de itertools; pero me pregunto por qué es más rápido que usar range o xrange.

    – si28719e

    4 de mayo de 2009 a las 6:02

  • @blackkettle: es más rápido porque no necesita devolver el índice de iteración actual, que es una parte medible del costo de xrange (y el rango de Python 3, que proporciona un iterador, no una lista). @nemo, el rango está tan optimizado como puede ser, pero la necesidad de crear y devolver una lista es inevitablemente un trabajo más pesado que un iterador (en Py3, el rango devuelve un iterador, como el xrange de Py2; la compatibilidad con versiones anteriores no permite tal cambio en Py2), especialmente uno que no necesita devolver un valor variable.

    – Alex Martelli

    7 mayo 2009 a las 14:17

  • @Cristian, sí, claramente preparando y devolviendo un Python int cada vez, inc. gc funciona, tiene un costo medible: usar un contador internamente no importa

    – Alex Martelli

    26 de septiembre de 2009 a las 23:04

  • Entiendo ahora. La diferencia proviene de la sobrecarga del GC, no del “algoritmo”. Por cierto, corro rápido cronométralo punto de referencia y la aceleración fue ~ 1.42x.

    – Cristian Ciupitu

    27 de septiembre de 2009 a las 0:28

Avatar de usuario de Ryan
Ryan

El modismo general para asignar a un valor que no se usa es nombrarlo _.

for _ in range(times):
    do_stuff()

Avatar de usuario de Ignacio Vázquez-Abrams
Ignacio Vázquez-Abrams

Lo que todos los que sugieren que uses _ no dicen es que _ se usa con frecuencia como atajo a uno de los obtener texto funciones, por lo que si desea que su software esté disponible en más de un idioma, es mejor que evite usarlo para otros fines.

import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print _('This is a translatable string.')

Aquí hay una idea aleatoria que utiliza (¿abusa?) modelo de datos (enlace Py3).

class Counter(object):
    def __init__(self, val):
        self.val = val

    def __nonzero__(self):
        self.val -= 1
        return self.val >= 0
    __bool__ = __nonzero__  # Alias to Py3 name to make code work unchanged on Py2 and Py3

x = Counter(5)
while x:
    # Do something
    pass

Me pregunto si hay algo como esto en las bibliotecas estándar.

  • Creo que tener un método como __nonzero__ con efectos secundarios es una idea horrible.

    – ThiefMaster

    22 de abril de 2012 a las 13:11

  • yo usaría __call__ en cambio. while x(): no es mucho más difícil de escribir.

    – Jasmin

    9 de julio de 2012 a las 14:16

  • También hay un argumento para evitar el nombre Counter; claro, no está reservado o en el ámbito integrado, pero collections.Counter es una cosay crear una clase con el mismo nombre corre el riesgo de que el mantenedor se confunda (no es que esto ya no sea un riesgo).

    – ShadowRanger

    3 de mayo de 2018 a las 13:17


Puede usar _11 (o cualquier número u otro identificador no válido) para evitar la colisión de nombres con gettext. Cada vez que usa un guión bajo + un identificador no válido, obtiene un nombre ficticio que se puede usar en el ciclo for.

  • Creo que tener un método como __nonzero__ con efectos secundarios es una idea horrible.

    – ThiefMaster

    22 de abril de 2012 a las 13:11

  • yo usaría __call__ en cambio. while x(): no es mucho más difícil de escribir.

    – Jasmin

    9 de julio de 2012 a las 14:16

  • También hay un argumento para evitar el nombre Counter; claro, no está reservado o en el ámbito integrado, pero collections.Counter es una cosay crear una clase con el mismo nombre corre el riesgo de que el mantenedor se confunda (no es que esto ya no sea un riesgo).

    – ShadowRanger

    3 de mayo de 2018 a las 13:17


Avatar de usuario de Anurag Uniyal
Anurag Uniyal

¿La respuesta puede depender del problema que tenga con el uso del iterador? puede ser uso

i = 100
while i:
    print i
    i-=1

o

def loop(N, doSomething):
    if not N:
        return
    print doSomething(N)
    loop(N-1, doSomething)

loop(100, lambda a:a)

pero, francamente, no veo ningún sentido en usar tales enfoques

  • Nota: Python (definitivamente no es el intérprete de referencia de CPython al menos, probablemente no la mayoría de los demás) no optimiza la recursión de cola, por lo que N se limitará a algo cercano al valor de sys.getrecursionlimit() (que por defecto está en algún lugar en el rango bajo de cuatro dígitos en CPython); usando sys.setrecursionlimit elevaría el límite, pero eventualmente alcanzaría el límite de la pila C y el intérprete moriría con un desbordamiento de la pila (no solo elevando un buen RuntimeError/RecursionError).

    – ShadowRanger

    20 de junio de 2018 a las 3:10


¿Ha sido útil esta solución?