O objetivo da tarefa era inicializar uma lista vazia chamada rand_array e preenchê-la com 10 números aleatórios exclusivos
Eu descobri a tarefa normalmente, seguindo as instruções do professor:
import random
rand_array = []
while len(rand_array) != 10:
lmnt = random.randint(1, 15)
if lmnt not in rand_array:
rand_array.append(lmnt)
print(rand_array)
Modifiquei-o mais tarde para ter inline para torná-lo mais eficiente, já que meu professor não gostava que eu usasse inline:
import random
rand_array = []
while len(rand_array) < 10:
lmnt = random.randint(1, 15)
rand_array.append(lmnt) if lmnt not in rand_array else None
Comecei a me questionar se isso seria realmente mais eficiente e se eu ainda conseguiria melhorar removendo a necessidade de inicializar uma lista vazia. Então, a pergunta principal é: "A segunda versão é mais eficiente que a primeira?" e também "Posso tornar a segunda versão ainda mais eficiente?"
Além disso, antes que alguém diga "Essa é uma tarefa tão pequena, não importa", se eu usar muito código embutido no futuro, preciso saber se a maneira como estou usando é mais eficiente do que o código não embutido.
Também peço desculpas antecipadamente se algo que digitei estiver impreciso.
Tecnicamente, seu inline é, na verdade, um pouco menos eficiente. Ele força o Python a:
None
valor noTrue
casoIsso não é apenas teórico; o bytecode CPython para a segunda abordagem (de
dis
) tem instruções extras justamente por esse motivo.Essa é uma diferença bem pequena, no entanto. Mais importante, a segunda abordagem é difícil de ler. Expressões ternárias são essencialmente para um caso de uso:
Seu caso de uso passa apenas no primeiro teste; não precisa de uma instrução else nem cria uma variável com base no resultado do if. Por esse motivo, um ternário é uma escolha pouco intuitiva. (Na verdade, precisei ler o código algumas vezes para descobrir por que ele não preencheu sua lista com
None
valores.) A instrução if é mais legível e pythonica.A melhor solução é não fazer nenhuma dessas opções. Em vez disso, use
random.sample
:Isso tem três vantagens: é mais legível, evita a necessidade de reinventar a roda e é mais rápido. Você pode comparar a velocidade de execução usando este script:
A diferença é bem drástica na minha máquina.
Talvez o intérprete consiga ler mais facilmente o primeiro do que o segundo ou vice-versa, mas não é de eficiência que estaríamos falando. Dê uma olhada nesta resposta .
Mas a substituição de != por < faz uma enorme diferença em larga escala, no sentido em que o primeiro é mais eficiente.
É verdade que < envolverá mais etapas de cálculo em termos de GATES do que !=, que exigirá apenas XOR.
Mas os resultados são frequentemente mascarados em CPUs reais por pipelining e previsão de ramificação.
Você pode testar aqui, embora o oposto do resultado proposto possa ser obtido às vezes.
Além disso, o segundo código está gerando muitos Nones e fazendo mau uso do código embutido.
Você pode considerar usar
if lmnt not in rand_array: rand_array.append(lmnt)
for inlineTambém, em geral, é um fato que, para fins de integração, estaríamos adicionando mais e mais complicações ao código