>>> range(1,11)
da-te
[1,2,3,4,5,6,7,8,9,10]
Por que não 1-11?
Eles decidiram fazer isso aleatoriamente ou tem algum valor que eu não estou vendo?
range()
faz sentido com muito mais frequência
>>> range(1,11)
da-te
[1,2,3,4,5,6,7,8,9,10]
Por que não 1-11?
Eles decidiram fazer isso aleatoriamente ou tem algum valor que eu não estou vendo?
range()
faz sentido com muito mais frequência
Respostas:
Porque é mais comum chamar range(0, 10)
what return [0,1,2,3,4,5,6,7,8,9]
que contém 10 elementos iguais len(range(0, 10))
. Lembre-se de que os programadores preferem a indexação baseada em 0.
Além disso, considere o seguinte snippet de código comum:
for i in range(len(li)):
pass
Você poderia ver que, se range()
fosse exatamente len(li)
isso, seria problemático? O programador precisa subtrair explicitamente 1. Isso também segue a tendência comum de programadores preferindo for(int i = 0; i < 10; i++)
mais for(int i = 0; i <= 9; i++)
.
Se você estiver chamando o intervalo com um início de 1 com frequência, convém definir sua própria função:
>>> def range1(start, end):
... return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
range(start, count)
?
range(10)
é equivalente a range(0, 10)
.
range1
não trabalhará com intervalos com um tamanho de etapa diferente de 1
.
for i in range(len(li)):
é um antipadrão. Deve-se usar enumerate
.
Embora existam algumas explicações algorítmicas úteis aqui, acho que pode ajudar a adicionar alguns argumentos simples da "vida real" sobre o porquê de funcionar dessa maneira, que achei úteis ao apresentar o assunto para jovens recém-chegados:
Com algo como 'range (1,10)', pode surgir confusão ao pensar que um par de parâmetros representa o "começo e o fim".
Na verdade, é iniciar e "parar".
Agora, se fosse o valor "final", sim, você pode esperar que esse número seja incluído como entrada final na sequência. Mas não é o "fim".
Outros chamam erroneamente esse parâmetro de "contagem" porque, se você usar apenas 'range (n)', é claro que itera 'n' vezes. Essa lógica quebra quando você adiciona o parâmetro start.
Portanto, o ponto principal é lembrar o nome: " stop ". Isso significa que é o ponto no qual, quando alcançada, a iteração será interrompida imediatamente. Não depois desse ponto.
Portanto, enquanto "start" realmente representa o primeiro valor a ser incluído, ao atingir o valor "stop", ele "quebra", em vez de continuar processando "esse também" antes de parar.
Uma analogia que usei para explicar isso às crianças é que, ironicamente, é melhor se comportar do que crianças! Não para depois que deveria - para imediatamente sem terminar o que estava fazendo. (Eles entendem isso;))
Outra analogia - quando você dirige um carro, você não passa por um sinal de stop / yield / 'give way' e acaba com ele sentado em algum lugar próximo ou atrás do seu carro. Tecnicamente, você ainda não o alcançou quando para. Não está incluído nas "coisas que você passou na sua jornada".
Espero que isso ajude a explicar o Pythonitos / Pythonitas!
Funciona bem em combinação com indexação baseada em zero e len()
. Por exemplo, se você tiver 10 itens em uma lista x
, eles serão numerados de 0 a 9. range(len(x))
dá 0-9.
Obviamente, as pessoas dirão que é mais um Pythonic a fazer for item in x
ou for index, item in enumerate(x)
melhor for i in range(len(x))
.
O fatiamento também funciona da seguinte maneira: foo[1:4]
são os itens 1-3 de foo
(lembrando que o item 1 é realmente o segundo item devido à indexação com base em zero). Por consistência, os dois devem funcionar da mesma maneira.
Penso nisso como: "o primeiro número desejado, seguido pelo primeiro número que você não deseja". Se você quer 1-10, o primeiro número que você não quer é 11, então érange(1, 11)
.
Se ficar complicado em um aplicativo específico, é fácil escrever uma pequena função auxiliar que adiciona 1 ao índice e chamadas finais range()
.
w = 'abc'; w[:] == w[0:len(w)]; w[:-1] == w[0:len(w)-1];
def full_range(start,stop): return range(start,stop+1) ## helper function
for index, item in enumerate(x)
a confusão evitar
Também é útil para dividir intervalos; range(a,b)
pode ser dividido em range(a, x)
e range(x, b)
, enquanto que com o intervalo inclusivo você escreveria um x-1
ou outro x+1
. Embora raramente seja necessário dividir intervalos, você tende a dividir listas com bastante frequência, e esse é um dos motivos pelos quais o corte de uma lista l[a:b]
inclui o a-ésimo elemento, mas não o a-ésimo. Então, range
ter a mesma propriedade a torna bastante consistente.
O comprimento do intervalo é o valor superior menos o valor inferior.
É muito parecido com algo como:
for (var i = 1; i < 11; i++) {
//i goes from 1 to 10 in here
}
em uma linguagem de estilo C.
Também como a linha de Ruby:
1...11 #this is a range from 1 to 10
No entanto, Ruby reconhece que muitas vezes você deseja incluir o valor do terminal e oferece a sintaxe alternativa:
1..10 #this is also a range from 1 to 10
1..10
vs 1...10
ao ler código!
Basicamente, em range(n)
iterações python n
vezes, que é de natureza exclusiva e é por isso que não fornece o último valor quando está sendo impresso, podemos criar uma função que fornece valor inclusivo, significa que também imprimirá o último valor mencionado no intervalo.
def main():
for i in inclusive_range(25):
print(i, sep=" ")
def inclusive_range(*args):
numargs = len(args)
if numargs == 0:
raise TypeError("you need to write at least a value")
elif numargs == 1:
stop = args[0]
start = 0
step = 1
elif numargs == 2:
(start, stop) = args
step = 1
elif numargs == 3:
(start, stop, step) = args
else:
raise TypeError("Inclusive range was expected at most 3 arguments,got {}".format(numargs))
i = start
while i <= stop:
yield i
i += step
if __name__ == "__main__":
main()
Considere o código
for i in range(10):
print "You'll see this 10 times", i
A idéia é que você obtenha uma lista de comprimento y-x
, que você pode (como você vê acima) iterar.
Leia os documentos python para obter o range - eles consideram a iteração de loop for a principal maneira de usar.
É apenas mais conveniente argumentar em muitos casos.
Basicamente, poderíamos pensar em um intervalo como um intervalo entre start
e end
. Se start <= end
, a duração do intervalo entre eles é end - start
. Se len
foi realmente definido como o comprimento, você teria:
len(range(start, end)) == start - end
No entanto, contamos os números inteiros incluídos no intervalo em vez de medir a duração do intervalo. Para manter a propriedade acima verdadeira, devemos incluir um dos pontos de extremidade e excluir o outro.
Adicionar o step
parâmetro é como introduzir uma unidade de comprimento. Nesse caso, você esperaria
len(range(start, end, step)) == (start - end) / step
para comprimento. Para obter a contagem, basta usar a divisão inteira.