The goal of the assignment was to initialize an empty list called rand_array then fill it with 10 unique random numbers
I figured out the assignment normally as per the teacher's directions:
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)
I modified it later to have inline to make it more efficient since my teacher didn't like me using 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
I started questioning if this was actually more efficient and if I could still make it better if I take off the requirement of initializing an empty list. So, the main question is: "Is the second version more efficient than the first?" and also "Can I make the second version even more efficient?"
Also, before anyone says, "This is such a small assignment, it doesn't matter", if I use lots of inline code in the future, I need to know if the way I'm using it is more efficient than non-inline code.
Also I apologize in advance if anything I have typed is inaccurate.
Technically, your inline is actually a little bit less efficient. It forces Python to:
None
value in the True
caseThis isn't just theoretical; the CPython bytecode for the second approach (from dis
) has extra instructions for precisely that reason.
This is a really small difference, though. More importantly, the second approach is hard to read. Ternary expressions are for essentially one use case:
Your use case only passes the first test; it neither needs an else statement nor creates a variable based on the result of the if. For that reason, a ternary is an unintuitive choice. (I actually had to read the code a couple times to figure out why it didn't fill your list with None
values.) The if statement is more readable and pythonic.
The actual best solution is to do neither of these. Instead, use random.sample
:
import random
rand_array = random.sample(range(1, 16), 10)
This has three advantages: it's more readable, it avoids reinventing the wheel, and it's faster. You can compare execution speed using this script:
import random
from timeit import timeit
def if_based():
rand_array = []
while len(rand_array) < 10:
lmnt = random.randint(1, 15)
if lmnt not in rand_array:
rand_array.append(lmnt)
return rand_array
def sample_based():
rand_array = random.sample(range(1, 16), 10)
return rand_array
print(f"If: {timeit(if_based)}")
print(f"Sample: {timeit(sample_based)}")
The difference is pretty drastic on my machine.
If: 6.120091282999965
Sample: 3.0449935650001407