Essa é uma boa pergunta! O PyDev até sinaliza o 'i' como um aviso para 'variável não utilizada'. A solução abaixo remove esse aviso.
Ashwin Nanjappa
@ Ashwin Você pode usar \ @UnusedVariable para remover esse aviso. Observe que eu precisava escapar do símbolo 'at' para que esse comentário fosse executado.
Raffi Khatchadourian
Eu encabeço a mesma pergunta que você. É irritante com avisos de pilão. É claro que você pode desativar os avisos por supressão adicional, como o @Raffi Khatchadourian proposto. Seria bom evitar avisos de pilão e comentários de supressão.
tangoal
Respostas:
110
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 ivariá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+23>>> _
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+23>>> _
9
E, de acordo com a gramática Python , é um nome de variável aceitável:
"Mas acho que você pode simplesmente viver com o" i "extra". Sim, é apenas um ponto acadêmico.
613 James McMahon
1
@ nemo, você pode tentar fazer _ no intervalo (n): se você não quiser usar nomes alfanuméricos.
Desconhecido
_ É uma variável nesse caso? Ou isso é algo mais em Python?
James McMahon
1
@nemo Sim, é apenas um nome de variável aceitável. No intérprete, é atribuída automaticamente a última expressão que você criou.
Desconhecido
3
@kurczak Há um ponto. O uso _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.
Fada Lambda
69
Você pode estar procurando
for _ in itertools.repeat(None, times):...
esta é a maneira mais rápida de repetir os timestempos no Python.
Eu não estava preocupado com o desempenho, apenas estava curioso se havia uma maneira mais tensa de escrever a declaração. Embora eu esteja usando esporadicamente o Python há cerca de 2 anos, ainda sinto muita falta. Itertools é uma dessas coisas, obrigado pela informação.
James McMahon
5
Isso é interessante, eu não estava ciente disso. Acabei de dar uma olhada nos documentos da ferramenta; mas eu me pergunto por que isso é mais rápido do que apenas usar range ou xrange?
Si28719e 04/04/09
5
@blackkettle: é mais rápido porque não precisa retornar o índice de iteração atual, que é uma parte mensurável do custo do xrange (e o intervalo do Python 3, que fornece um iterador, não uma lista). @nemo, o range é o mais otimizado possível, mas a necessidade de criar e retornar uma lista é inevitavelmente mais trabalhosa do que um iterador (no Py3, o range retorna um iterador, como o xrange do Py2; a compatibilidade com versões anteriores não permite essa alteração no Py2), especialmente aquele que não precisa retornar um valor variável.
Alex Martelli
4
@ Cristian, sim, claramente preparando e retornando um Python int toda vez, inc. gc, tem um custo mensurável - não é necessário usar um contador internamente .
2828 Alex Martelli
4
Eu entendo agora. A diferença vem da sobrecarga do GC, não do "algoritmo". A propósito, eu corro uma referência de tempo rápida e a aceleração foi de ~ 1,42x.
Cristian Ciupitu 27/09/09
59
O idioma geral para atribuir a um valor que não é usado é nomeá-lo _.
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.')
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
Gostaria de saber se existe algo assim nas bibliotecas padrão?
Eu acho que ter um método como os __nonzero__efeitos colaterais é uma ideia horrível.
ThiefMaster
2
Eu usaria em seu __call__lugar. while x():não é muito mais difícil de escrever.
Jasmijn
1
Há também um argumento para evitar o nome 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).
ShadowRanger
7
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.
Nota: Python (definitivamente não é o intérprete de referência do CPython, pelo menos, provavelmente não a maioria dos outros) não otimiza a recursão da cauda; portanto, N será limitado a algo próximo do valor de sys.getrecursionlimit()(que é o padrão em algum lugar entre os quatro baixos). intervalo de dígitos no CPython); O uso sys.setrecursionlimitaumentaria 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).
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.
Eu geralmente concordo com as soluções dadas acima. Ou seja, com:
Usando sublinhado em for-loop (2 e mais linhas)
Definindo um whilecontador normal (3 e mais linhas)
Declarando uma classe personalizada com __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.
AChampion
0
Nós nos divertimos com o seguinte, interessante para compartilhar:
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()
Se do_somethingé uma função simples ou pode ser agrupada em uma, uma simples map()lata pode 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)
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)
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.
Obviamente, isso é intencionalmente patológico, portanto, criticar é irrelevante, mas observarei uma armadilha adicional aqui. No CPython, o intérprete de referência, as definições de classe são naturalmente cíclicas (a criação inevitável de uma classe cria um ciclo de referência que impede a limpeza determinística da classe com base na contagem de referências). Isso significa que você está esperando no GC cíclico para iniciar e limpar a classe. Geralmente, ele é coletado como parte da geração mais jovem, que por padrão é coletada com frequência, mas, mesmo assim, cada loop significa ~ 1,5 KB de lixo com vida útil não determinística.
ShadowRanger
Basicamente, para evitar uma variável nomeada que seria (normalmente) limpa de forma determinística em cada loop (quando é recuperada e o valor antigo limpo), você está criando uma enorme variável sem nome que é limpa de forma não determinística e pode facilmente durar mais tempo.
ShadowRanger
-2
#Return first n items of the iterable as a list
list(itertools.islice(iterable, n))
Esse é um loop infinito, pois a condição range(some_number)é sempre verdadeira!
mortal
@eadly: Bem, se 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 rangeobjeto (Py3) para cada teste (não é uma constante do ponto de vista do intérprete, ele precisa carregar rangee some_numbercada loop, chame rangee teste o resultado).
Respostas:
Do alto da minha cabeça, não.
Eu acho que o melhor que você poderia fazer é algo assim:
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.Observe que
_
é atribuído o último resultado retornado em uma sessão python interativa: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.
E, de acordo com a gramática Python , é um nome de variável aceitável:
fonte
_
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
esta é a maneira mais rápida de repetir os
times
tempos no Python.fonte
O idioma geral para atribuir a um valor que não é usado é nomeá-lo
_
.fonte
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.
fonte
_
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 ).
Gostaria de saber se existe algo assim nas bibliotecas padrão?
fonte
__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, mascollections.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.
fonte
Pode ser que a resposta dependa de qual problema você tem ao usar o iterador? pode ser usado
ou
mas, francamente, não vejo sentido em usar essas abordagens
fonte
sys.getrecursionlimit()
(que é o padrão em algum lugar entre os quatro baixos). intervalo de dígitos no CPython); O usosys.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 bomRuntimeError
/RecursionError
).RESULTADO:
fonte
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.
fonte
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.
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 .
fonte
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:
Resultados:
fonte
Se
do_something
é uma função simples ou pode ser agrupada em uma, uma simplesmap()
lata podedo_something
range(some_number)
:Se você deseja passar argumentos
do_something
, também pode achar que a receita do itertoolsrepeatfunc
lê bem:Para passar os mesmos argumentos:
Para passar argumentos diferentes:
fonte
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:
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.fonte
Retirado de http://docs.python.org/2/library/itertools.html
fonte
A respeito:
fonte
range(some_number)
é sempre verdadeira!some_number
é menor ou igual a0
, não é infinito, ele simplesmente nunca é executado. :-) E é bastante ineficiente para um loop infinito (especialmente no Py2), uma vez que cria um novolist
(Py2) ourange
objeto (Py3) para cada teste (não é uma constante do ponto de vista do intérprete, ele precisa carregarrange
esome_number
cada loop, chamerange
e teste o resultado).