É possível fazer o seguinte sem o i
?
for i in range(some_number):
# do something
Se você quiser fazer algo N várias vezes e não precisar do iterador.
É possível fazer o seguinte sem o i
?
for i in range(some_number):
# do something
Se você quiser fazer algo N várias vezes e não precisar do iterador.
Respostas:
Do alto da minha cabeça, não.
Eu acho que o melhor que você poderia fazer é algo assim:
def loop(f,n):
for i in xrange(n): f()
loop(lambda: <insert expression here>, 5)
Mas acho que você pode simplesmente viver com a i
variável extra .
Aqui está a opção de usar a _
variável, que na realidade é apenas outra variável.
for _ in range(n):
do_something()
Observe que _
é atribuído o último resultado retornado em uma sessão python interativa:
>>> 1+2
3
>>> _
3
Por esse motivo, eu não o usaria dessa maneira. Não conheço nenhum idioma mencionado por Ryan. Isso pode atrapalhar o seu intérprete.
>>> for _ in xrange(10): pass
...
>>> _
9
>>> 1+2
3
>>> _
9
E, de acordo com a gramática Python , é um nome de variável aceitável:
identifier ::= (letter|"_") (letter | digit | "_")*
_
deixa claro que deve ser ignorado. Dizer que não há sentido em fazer isso é como dizer que não há sentido em comentar seu código - porque faria exatamente o mesmo.
Você pode estar procurando
for _ in itertools.repeat(None, times): ...
esta é a maneira mais rápida de repetir os times
tempos no Python.
O que todo mundo sugerindo que você use _ não está dizendo é que _ é freqüentemente usado como um atalho para uma das funções gettext ; portanto, se você deseja que seu software esteja disponível em mais de um idioma, é melhor evitar usá-lo. para outros fins.
import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print _('This is a translatable string.')
_
parece uma péssima idéia, não me importaria de entrar em conflito com ela.
Aqui está uma ideia aleatória que utiliza (abusos?) O modelo de dados ( link 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
Gostaria de saber se existe algo assim nas bibliotecas padrão?
__nonzero__
efeitos colaterais é uma ideia horrível.
__call__
lugar. while x():
não é muito mais difícil de escrever.
Counter
; com certeza, não está reservado ou no escopo interno, mas collections.Counter
é uma coisa , e criar uma classe com o mesmo nome arrisca a confusão do mantenedor (não que isso já não esteja arriscando isso).
Você pode usar _11 (ou qualquer número ou outro identificador inválido) para impedir a colisão de nomes com o gettext. Sempre que você usa sublinhado + identificador inválido, você obtém um nome falso que pode ser usado no loop for.
Pode ser que a resposta dependa de qual problema você tem ao usar o iterador? pode ser usado
i = 100
while i:
print i
i-=1
ou
def loop(N, doSomething):
if not N:
return
print doSomething(N)
loop(N-1, doSomething)
loop(100, lambda a:a)
mas, francamente, não vejo sentido em usar essas abordagens
sys.getrecursionlimit()
(que é o padrão em algum lugar entre os quatro baixos). intervalo de dígitos no CPython); O uso sys.setrecursionlimit
aumentaria o limite, mas, eventualmente, você atingiria o limite da pilha C e o intérprete morreria com um estouro de pilha (não apenas aumentando um bom RuntimeError
/ RecursionError
).
t=0
for _ in range(10):
print t
t = t+1
RESULTADO:
0
1
2
3
4
5
6
7
8
9
Em vez de um contador desnecessário, agora você tem uma lista desnecessária. A melhor solução é usar uma variável que comece com "_", que informa aos verificadores de sintaxe que você sabe que não está usando a variável.
x = range(5)
while x:
x.pop()
print "Work!"
Eu geralmente concordo com as soluções dadas acima. Ou seja, com:
for
-loop (2 e mais linhas)while
contador normal (3 e mais linhas)__nonzero__
implementação (muito mais linhas)Se alguém definir um objeto como em # 3, eu recomendaria implementar o protocolo with with keyword ou aplicar contextlib .
Além disso, proponho outra solução. É um forro de 3 linhas e não é de suprema elegância, mas usa o pacote itertools e, portanto, pode ser de seu interesse.
from itertools import (chain, repeat)
times = chain(repeat(True, 2), repeat(False))
while next(times):
print 'do stuff!'
Neste exemplo, 2 é o número de vezes para iterar o loop. A cadeia está agrupando dois iteradores repetidos , o primeiro sendo limitado, mas o segundo é infinito. Lembre-se de que esses são objetos iteradores verdadeiros, portanto, eles não requerem memória infinita. Obviamente, isso é muito mais lento que a solução 1 . A menos que seja escrito como parte de uma função, pode ser necessária uma limpeza para a variável times .
chain
é desnecessário, times = repeat(True, 2); while next(times, False):
faz a mesma coisa.
Nós nos divertimos com o seguinte, interessante para compartilhar:
class RepeatFunction:
def __init__(self,n=1): self.n = n
def __call__(self,Func):
for i in xrange(self.n):
Func()
return Func
#----usage
k = 0
@RepeatFunction(7) #decorator for repeating function
def Job():
global k
print k
k += 1
print '---------'
Job()
Resultados:
0
1
2
3
4
5
6
---------
7
Se do_something
é uma função simples ou pode ser agrupada em uma, uma simples map()
lata pode do_something
range(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)
Se você deseja passar argumentos do_something
, também pode achar que a receita do itertoolsrepeatfunc
lê bem:
Para passar os mesmos argumentos:
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)
Para passar argumentos diferentes:
argses = [(1, 2), (3, 4), ...]
deque(starmap(do_something, argses), 0)
Se você realmente deseja evitar colocar algo com um nome (seja uma variável de iteração como no OP, ou uma lista indesejada ou um gerador indesejado retornando verdadeiro a quantidade de tempo desejada), você pode fazer isso se realmente quiser:
for type('', (), {}).x in range(somenumber):
dosomething()
O truque usado é criar uma classe anônima type('', (), {})
que resulta em uma classe com nome vazio, mas NB: ela não é inserida no espaço para nome local ou global (mesmo que um nome não vazio tenha sido fornecido). Em seguida, você usa um membro dessa classe como variável de iteração inacessível, pois a classe da qual ele é membro é inacessível.
#Return first n items of the iterable as a list
list(itertools.islice(iterable, n))
Retirado de http://docs.python.org/2/library/itertools.html
A respeito:
while range(some_number):
#do something
range(some_number)
é sempre verdadeira!
some_number
é menor ou igual a 0
, não é infinito, ele simplesmente nunca é executado. :-) E é bastante ineficiente para um loop infinito (especialmente no Py2), uma vez que cria um novo list
(Py2) ou range
objeto (Py3) para cada teste (não é uma constante do ponto de vista do intérprete, ele precisa carregar range
e some_number
cada loop, chame range
e teste o resultado).