# blackjack dealer hand generator

I wrote a piece of blackjack code - for dealer dealing cards to himself (python). My question is how can I make it more efficient, faster and neater. I ran it for 1.000.000 iterations and it took 14.7 second which is quite slow, I believe.

import random
deck = 4 * [2,3,4,5,6,7,8,9,10,10,10,10,11]
random.shuffle(deck)

dealer_hand = []
dealer_hand.append(deck.pop(0))
dealer_hand.append(deck.pop(0))
hit_on_soft_17 = True
exit = False

while not exit:
if sum(dealer_hand) == 17 and hit_on_soft_17:
exit = True
for i, card in enumerate(dealer_hand):
if card == 11:
exit = False
dealer_hand.append(deck.pop(0))
break
if sum(dealer_hand) < 17:
exit = False
dealer_hand.append(deck.pop(0))
if sum(dealer_hand) > 21:
exit = True
for i, card in enumerate(dealer_hand):
if card == 11:
exit = False
dealer_hand[i] = 1
break
if sum(dealer_hand) < 22 and sum(dealer_hand) > 17:
exit = True

print(dealer_hand)

• Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to edit and give it a different title if there is something more appropriate. Sep 16 at 15:54
• Why would a dealer need to run this a million times? Things don't need to be faster than necessary for your use case. Popping the back of a list is faster than the front, although the gains may be negligible for such a tiny list. You're also summing the hand unnecessarily many times. You can store that in a variable. Again, sort of a micro optimization. Sep 16 at 21:27

# Testing

One million print(dealer_hand) statements executed in 14.7 seconds would be amazing. I'm running it as I write this answer and it has yet to finish. Please be clear on exactly what you are timing.

# pop

deck.pop(0) is inefficient, since every element in the list must be copied to a new position. Consider instead using deck.pop() to remove a card from the other end of the deck. Alternately, you could use a deque, which allows O(1) insertion/removal from either end. Finally, you could create an iterator (it = iter(deck)) and use it to deal cards (next(it)); it doesn't actually remove the cards from deck, but iterates through them one-by-one.

# sum

If the dealer holds [10, 8], then sum(dealer_hand) is computed 5 times in the loop! Each time, the same value is returned. You could compute this once at the top of the loop, dealer_total = sum(dealer_hand), and use that variable in subsequent tests.

# Chained conditionals

if sum(dealer_hand) < 22 and sum(dealer_hand) > 17: could be written more succinctly and more efficiently as if 17 < sum(dealer_hand) < 22: Of course, if 17 < dealer_total < 22: is better still.

# Reserved identifiers

exit() is a function ... or it was until you redefined it as a variable. Use a different identifier, like done, instead.

# Bug

If hit_on_soft_17 = False, then once the dealer holds [10, 7] (or equivalent), none of the if conditions will be true, exit will remain False, and the loop will never end.

# PEP-0008

• hit_on_soft_17 is a global constant, and should be named in UPPER_CASE like HIT_ON_SOFT_17.
• Commas should be followed by 1 space

# Use functions

You should always organize your code into functions.