¡Esta es una buena pregunta! PyDev incluso marca la 'i' como advertencia de 'variable no utilizada'. La solución a continuación elimina esta advertencia.
Ashwin Nanjappa
@Ashwin Puede usar \ @UnusedVariable para eliminar esa advertencia. Tenga en cuenta que necesitaba escapar del símbolo 'at' para que este comentario pasara.
Raffi Khatchadourian
Yo te hago la misma pregunta. Es molesto con advertencias de pylint. Por supuesto, puede deshabilitar las advertencias mediante supresión adicional, como propuso @Raffi Khatchadourian. Sería bueno evitar las advertencias de pylint y los comentarios de supresión.
Tangoal
Respuestas:
110
Fuera de mi cabeza, no.
Creo que lo mejor que puedes 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 la _variable, que en realidad es solo otra variable.
for _ in range(n):
do_something()
Tenga en cuenta que _se le asigna el último resultado que regresó en una sesión interactiva de Python:
>>>1+23>>> _
3
Por esta razón, no lo usaría de esta manera. No conozco ningún idioma como lo menciona Ryan. Puede estropear a su intérprete.
>>>for _ in xrange(10):pass...>>> _
9>>>1+23>>> _
9
Y de acuerdo con la gramática de Python , es un nombre de variable aceptable:
"Pero creo que puedes vivir con la" i "adicional" Sí, es solo un punto académico.
James McMahon
1
@nemo, puedes intentar hacerlo para _ en el rango (n): si no quieres usar nombres alfanuméricos.
Desconocido
¿Es _ una variable en ese caso? ¿O es algo más en Python?
James McMahon
1
@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
3
@kurczak Hay un punto. El uso _deja en claro que debe ignorarse. Decir que no tiene sentido hacer esto es como decir que no tiene sentido comentar su código, porque de todos modos haría exactamente lo mismo.
Lambda Fairy
69
Usted puede estar buscando
for _ in itertools.repeat(None, times):...
Esta es LA forma más rápida de iterar timestiempos en Python.
No me preocupaba el rendimiento, solo tenía curiosidad por saber si había una forma más simple de escribir la declaración. Si bien he estado usando Python esporádicamente durante aproximadamente 2 años, todavía siento que me faltan muchas cosas. Itertools es una de esas cosas, gracias por la información.
James McMahon
55
Eso es interesante, no estaba al tanto de eso. Acabo de echar un vistazo a los documentos de itertools; pero me pregunto por qué es esto más rápido que solo usar rango o xrange?
si28719e
55
@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 construir 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
44
@Cristian, sí, claramente preparando y devolviendo un Python int cada vez, inc. gc work, tiene un costo medible: usar un contador internamente no importa.
Alex Martelli
44
Entiendo ahora. La diferencia proviene de la sobrecarga del GC, no del "algoritmo". Por cierto, ejecuté un tiempo de referencia rápido y la aceleración fue de ~ 1.42x.
Cristian Ciupitu
59
El idioma general para asignar a un valor que no se utiliza es nombrarlo _.
Lo que todo el mundo sugiere que use _ no dice que _ se usa con frecuencia como un acceso directo a una de las funciones gettext , 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.')
classCounter(object):def __init__(self, val):
self.val = val
def __nonzero__(self):
self.val -=1return self.val >=0
__bool__ = __nonzero__ # Alias to Py3 name to make code work unchanged on Py2 and Py3
x =Counter(5)while x:# Do somethingpass
Me pregunto si hay algo como esto en las bibliotecas estándar.
Creo que tener un método como __nonzero__los efectos secundarios es una idea horrible.
ThiefMaster
2
Yo usaría en su __call__lugar. while x():No es mucho más difícil de escribir.
Jasmijn
1
También hay un argumento para evitar el nombre Counter; claro, no está reservado ni está dentro del alcance incorporado, pero collections.Counteres una cosa , y crear una clase del mismo nombre conlleva el riesgo de confusión del mantenedor (no es que esto ya no se arriesgue).
ShadowRanger
7
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 guión bajo + identificador inválido, obtiene un nombre ficticio que puede usarse para bucle.
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 la cola, por lo que N se limitará a algo cercano al valor de sys.getrecursionlimit()(que por defecto está en algún lugar entre los cuatro bajos rango de dígitos en CPython); usar sys.setrecursionlimitaumentaría el límite, pero eventualmente alcanzarías 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).
En lugar de un contador innecesario, ahora tiene una lista innecesaria. La mejor solución es usar una variable que comience con "_", que le dice a los verificadores de sintaxis que usted sabe que no está usando la variable.
Generalmente estoy de acuerdo con las soluciones dadas anteriormente. A saber con:
Usando guión bajo en for -loop (2 y más líneas)
Definiendo un normal while contador (3 y más líneas)
Declarar una clase personalizada con __nonzero__implementación (muchas más líneas)
Si se trata de definir un objeto como en el n . ° 3 , recomendaría implementar el protocolo con la palabra clave o aplicar contextlib .
Además, propongo otra solución. Es un revestimiento de 3 y no es de la elegancia suprema, pero utiliza el paquete itertools y, por lo tanto, puede ser de interés.
from itertools import(chain, repeat)
times = chain(repeat(True,2), repeat(False))while next(times):print'do stuff!'
En este ejemplo, 2 es el número de veces que se repite el ciclo. cadena está envolviendo dos repetición iteradores, el primer ser limitada, pero la segunda es infinito. Recuerde que estos son verdaderos objetos iteradores, por lo tanto, no requieren memoria infinita. Obviamente, esto es mucho más lento que la solución n . ° 1 . A menos que esté escrito como parte de una función, puede requerir una limpieza por tiempos variables.
chainEs innecesario, times = repeat(True, 2); while next(times, False):hace lo mismo.
AChampion
0
Nos hemos divertido con lo siguiente, interesante para compartir:
classRepeatFunction:def __init__(self,n=1): self.n = n
def __call__(self,Func):for i in xrange(self.n):Func()returnFunc#----usage
k =0@RepeatFunction(7)#decorator for repeating functiondefJob():global k
print k
k +=1print'---------'Job()
Si do_somethinges una función simple o puede envolverse en una, una map()lata simple puede ser do_somethingrange(some_number):
# Py2 version - map is eager, so it can be used alone
map(do_something, xrange(some_number))# Py3 version - map is lazy, so it must be consumed to do the work at all;# wrapping in list() would be equivalent to Py2, but if you don't use the return# value, it's wastefully creating a temporary, possibly huge, list of junk.# collections.deque with maxlen 0 can efficiently run a generator to exhaustion without# storing any of the results; the itertools consume recipe uses it for that purpose.from collections import deque
deque(map(do_something, range(some_number)),0)
from collections import deque
from itertools import repeat, starmap
args =(..., my args here,...)# Same as Py3 map above, you must consume starmap (it's a lazy generator, even on Py2)
deque(starmap(do_something, repeat(args, some_number)),0)
Si realmente desea evitar poner algo con un nombre (ya sea una variable de iteración como en el OP, o una lista no deseada o un generador no deseado que devuelve el tiempo deseado), puede hacerlo si realmente lo desea:
for type('',(),{}).x in range(somenumber):
dosomething()
El truco que se usa es crear una clase anónima type('', (), {})que da como resultado una clase con un nombre vacío, pero NB que no se inserta en el espacio de nombres local o global (incluso si se proporcionó un nombre no vacío). Luego usa un miembro de esa clase como variable de iteración que no es accesible ya que la clase de la que es miembro es inalcanzable.
Obviamente, esto es intencionalmente patológico, por lo que criticarlo no viene al caso, pero notaré un escollo adicional aquí. En CPython, el intérprete de referencia, las definiciones de clase son naturalmente cíclicas (crear una clase inevitablemente crea un ciclo de referencia que impide la limpieza determinista de la clase basada en el recuento de referencias). Eso significa que estás esperando que el GC cíclico entre en acción y limpie la clase. Por lo general, se recolectará como parte de la generación más joven, que por defecto se recolecta con frecuencia, pero aún así, cada ciclo significa ~ 1.5 KB de basura con vida no determinista.
ShadowRanger
Básicamente, para evitar una variable con nombre que se limpie (típicamente) de manera determinista en cada bucle (cuando se rebota y se limpia el valor anterior), está creando una gran variable sin nombre que se limpia de manera no determinista y podría fácilmente durar más.
ShadowRanger
-2
#Return first n items of the iterable as a list
list(itertools.islice(iterable, n))
¡Es un bucle infinito ya que la condición range(some_number)siempre es cierta!
mortal
@deadly: Bueno, si some_numberes menor o igual que 0, no es infinito, simplemente nunca se ejecuta. :-) Y es bastante ineficiente para un bucle infinito (especialmente en Py2), ya que crea un nuevo list(Py2) u rangeobjeto (Py3) para cada prueba (no es una constante desde el punto de vista del intérprete, tiene que cargar rangey some_numbercada ciclo, llame range, luego pruebe el resultado).
Respuestas:
Fuera de mi cabeza, no.
Creo que lo mejor que puedes hacer es algo como esto:
Pero creo que puedes vivir con el extra
i
variable .Aquí está la opción de usar la
_
variable, que en realidad es solo otra variable.Tenga en cuenta que
_
se le asigna el último resultado que regresó en una sesión interactiva de Python:Por esta razón, no lo usaría de esta manera. No conozco ningún idioma como lo menciona Ryan. Puede estropear a su intérprete.
Y de acuerdo con la gramática de Python , es un nombre de variable aceptable:
fuente
_
deja en claro que debe ignorarse. Decir que no tiene sentido hacer esto es como decir que no tiene sentido comentar su código, porque de todos modos haría exactamente lo mismo.Usted puede estar buscando
Esta es LA forma más rápida de iterar
times
tiempos en Python.fuente
El idioma general para asignar a un valor que no se utiliza es nombrarlo
_
.fuente
Lo que todo el mundo sugiere que use _ no dice que _ se usa con frecuencia como un acceso directo a una de las funciones gettext , por lo que si desea que su software esté disponible en más de un idioma, es mejor que evite usarlo para otros fines
fuente
_
parece una idea terrible, no me importaría entrar en conflicto con ella.Aquí hay una idea aleatoria que utiliza (¿abusos?) El modelo de datos ( enlace Py3 ).
Me pregunto si hay algo como esto en las bibliotecas estándar.
fuente
__nonzero__
los efectos secundarios es una idea horrible.__call__
lugar.while x():
No es mucho más difícil de escribir.Counter
; claro, no está reservado ni está dentro del alcance incorporado, perocollections.Counter
es una cosa , y crear una clase del mismo nombre conlleva el riesgo de confusión del mantenedor (no es que esto ya no se arriesgue).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 guión bajo + identificador inválido, obtiene un nombre ficticio que puede usarse para bucle.
fuente
¿Puede ser la respuesta dependerá de qué problema tiene con el uso de iterador? puede ser uso
o
pero francamente no veo ningún punto en usar tales enfoques
fuente
sys.getrecursionlimit()
(que por defecto está en algún lugar entre los cuatro bajos rango de dígitos en CPython); usarsys.setrecursionlimit
aumentaría el límite, pero eventualmente alcanzarías el límite de la pila C y el intérprete moriría con un desbordamiento de la pila (no solo elevando un buenRuntimeError
/RecursionError
).SALIDA:
fuente
En lugar de un contador innecesario, ahora tiene una lista innecesaria. La mejor solución es usar una variable que comience con "_", que le dice a los verificadores de sintaxis que usted sabe que no está usando la variable.
fuente
Generalmente estoy de acuerdo con las soluciones dadas anteriormente. A saber con:
for
-loop (2 y más líneas)while
contador (3 y más líneas)__nonzero__
implementación (muchas más líneas)Si se trata de definir un objeto como en el n . ° 3 , recomendaría implementar el protocolo con la palabra clave o aplicar contextlib .
Además, propongo otra solución. Es un revestimiento de 3 y no es de la elegancia suprema, pero utiliza el paquete itertools y, por lo tanto, puede ser de interés.
En este ejemplo, 2 es el número de veces que se repite el ciclo. cadena está envolviendo dos repetición iteradores, el primer ser limitada, pero la segunda es infinito. Recuerde que estos son verdaderos objetos iteradores, por lo tanto, no requieren memoria infinita. Obviamente, esto es mucho más lento que la solución n . ° 1 . A menos que esté escrito como parte de una función, puede requerir una limpieza por tiempos variables.
fuente
chain
Es innecesario,times = repeat(True, 2); while next(times, False):
hace lo mismo.Nos hemos divertido con lo siguiente, interesante para compartir:
Resultados:
fuente
Si
do_something
es una función simple o puede envolverse en una, unamap()
lata simple puede serdo_something
range(some_number)
:Si desea pasar argumentos a
do_something
, también puede encontrar la receta de itertoolsrepeatfunc
lee bien:Para pasar los mismos argumentos:
Para pasar diferentes argumentos:
fuente
Si realmente desea evitar poner algo con un nombre (ya sea una variable de iteración como en el OP, o una lista no deseada o un generador no deseado que devuelve el tiempo deseado), puede hacerlo si realmente lo desea:
El truco que se usa es crear una clase anónima
type('', (), {})
que da como resultado una clase con un nombre vacío, pero NB que no se inserta en el espacio de nombres local o global (incluso si se proporcionó un nombre no vacío). Luego usa un miembro de esa clase como variable de iteración que no es accesible ya que la clase de la que es miembro es inalcanzable.fuente
Tomado de http://docs.python.org/2/library/itertools.html
fuente
Qué pasa:
fuente
range(some_number)
siempre es cierta!some_number
es menor o igual que0
, no es infinito, simplemente nunca se ejecuta. :-) Y es bastante ineficiente para un bucle infinito (especialmente en Py2), ya que crea un nuevolist
(Py2) urange
objeto (Py3) para cada prueba (no es una constante desde el punto de vista del intérprete, tiene que cargarrange
ysome_number
cada ciclo, llamerange
, luego pruebe el resultado).