Random iteration over a deck of cards












1















I am trying to randomly iterate over a deck of cards with no repetition.



Following is the code:



import random

class Cards:

# Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
12: 'dQueen', 13: 'dKing', 14: 'dAce'},
{2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
12: 'hQueen', 13: 'hKing', 14: 'hAce'},
{2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
12: 'sQueen', 13: 'sKing', 14: 'sAce'},
{2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
12: 'cQueen', 13: 'cKing', 14: 'cAce'}]

def random_pick(self): # Method to randomly pick a card from the deck

choice = random.choice(random.choice(self.total_cards))

for v in self.total_cards: # to retrieve the corresponding `key` for `choice`
for i in v.values():
if choice == i:
k = v[i]
v.pop(k)

print(choice) # To print the random card picked from the deck
print(self.total_cards) # To print the updated Deck after picking the card


c = Cards()
c.random_pick()


The idea that I am trying to work with is, as soon as the card is picked, it should be removed from the deck.



This is the error :



Traceback (most recent call last):
File "F:/Blackjack/Base/Cards.py", line 30, in <module>
c.random_pick()
File "F:/Blackjack/Base/Cards.py", line 17, in random_pick
choice = random.choice(random.choice(self.total_cards))
File "C:UsersPythonPython37-32librandom.py", line 262, in choice
return seq[i]
KeyError: 0


From my understanding, KeyError is an exception raised when a mapping (dictionary) key is not found in the set of existing keys. But my IF LOOP is TRUE only when the condition choice == i and only then should the pop() be initiated.



I have tried the above code without the pop() method in the code and the code works just fine, generating random cards after every run.










share|improve this question




















  • 2





    It's way easier to shuffle the deck instead, like you do in a real card game.

    – user2357112
    Nov 24 '18 at 10:15











  • Why don't you store all the cards in an array and then simply shuffle the array using random.shuffle(array)? Traversal over the shuffled array will be same as randomly iterating over array. Is there any specific reason you want to go for this data-structure?

    – Lavish Kothari
    Nov 24 '18 at 10:26











  • @LavishKothari hi, i know that arrays would do the trick but i am trying to teach myself OOP with DS with an example. Its not mandatory to use DS but that's the goal i started with.

    – 404 Brain Not Found
    Nov 24 '18 at 10:35











  • @user2357112 but that still presents a possibility that an already used card might still reappear. I have to be able to remove the card once it is used

    – 404 Brain Not Found
    Nov 24 '18 at 10:37













  • @404BrainNotFound: Shuffle a list, then draw cards off the end with pop(), or iterate with for. No repetition.

    – user2357112
    Nov 24 '18 at 10:59
















1















I am trying to randomly iterate over a deck of cards with no repetition.



Following is the code:



import random

class Cards:

# Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
12: 'dQueen', 13: 'dKing', 14: 'dAce'},
{2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
12: 'hQueen', 13: 'hKing', 14: 'hAce'},
{2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
12: 'sQueen', 13: 'sKing', 14: 'sAce'},
{2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
12: 'cQueen', 13: 'cKing', 14: 'cAce'}]

def random_pick(self): # Method to randomly pick a card from the deck

choice = random.choice(random.choice(self.total_cards))

for v in self.total_cards: # to retrieve the corresponding `key` for `choice`
for i in v.values():
if choice == i:
k = v[i]
v.pop(k)

print(choice) # To print the random card picked from the deck
print(self.total_cards) # To print the updated Deck after picking the card


c = Cards()
c.random_pick()


The idea that I am trying to work with is, as soon as the card is picked, it should be removed from the deck.



This is the error :



Traceback (most recent call last):
File "F:/Blackjack/Base/Cards.py", line 30, in <module>
c.random_pick()
File "F:/Blackjack/Base/Cards.py", line 17, in random_pick
choice = random.choice(random.choice(self.total_cards))
File "C:UsersPythonPython37-32librandom.py", line 262, in choice
return seq[i]
KeyError: 0


From my understanding, KeyError is an exception raised when a mapping (dictionary) key is not found in the set of existing keys. But my IF LOOP is TRUE only when the condition choice == i and only then should the pop() be initiated.



I have tried the above code without the pop() method in the code and the code works just fine, generating random cards after every run.










share|improve this question




















  • 2





    It's way easier to shuffle the deck instead, like you do in a real card game.

    – user2357112
    Nov 24 '18 at 10:15











  • Why don't you store all the cards in an array and then simply shuffle the array using random.shuffle(array)? Traversal over the shuffled array will be same as randomly iterating over array. Is there any specific reason you want to go for this data-structure?

    – Lavish Kothari
    Nov 24 '18 at 10:26











  • @LavishKothari hi, i know that arrays would do the trick but i am trying to teach myself OOP with DS with an example. Its not mandatory to use DS but that's the goal i started with.

    – 404 Brain Not Found
    Nov 24 '18 at 10:35











  • @user2357112 but that still presents a possibility that an already used card might still reappear. I have to be able to remove the card once it is used

    – 404 Brain Not Found
    Nov 24 '18 at 10:37













  • @404BrainNotFound: Shuffle a list, then draw cards off the end with pop(), or iterate with for. No repetition.

    – user2357112
    Nov 24 '18 at 10:59














1












1








1








I am trying to randomly iterate over a deck of cards with no repetition.



Following is the code:



import random

class Cards:

# Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
12: 'dQueen', 13: 'dKing', 14: 'dAce'},
{2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
12: 'hQueen', 13: 'hKing', 14: 'hAce'},
{2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
12: 'sQueen', 13: 'sKing', 14: 'sAce'},
{2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
12: 'cQueen', 13: 'cKing', 14: 'cAce'}]

def random_pick(self): # Method to randomly pick a card from the deck

choice = random.choice(random.choice(self.total_cards))

for v in self.total_cards: # to retrieve the corresponding `key` for `choice`
for i in v.values():
if choice == i:
k = v[i]
v.pop(k)

print(choice) # To print the random card picked from the deck
print(self.total_cards) # To print the updated Deck after picking the card


c = Cards()
c.random_pick()


The idea that I am trying to work with is, as soon as the card is picked, it should be removed from the deck.



This is the error :



Traceback (most recent call last):
File "F:/Blackjack/Base/Cards.py", line 30, in <module>
c.random_pick()
File "F:/Blackjack/Base/Cards.py", line 17, in random_pick
choice = random.choice(random.choice(self.total_cards))
File "C:UsersPythonPython37-32librandom.py", line 262, in choice
return seq[i]
KeyError: 0


From my understanding, KeyError is an exception raised when a mapping (dictionary) key is not found in the set of existing keys. But my IF LOOP is TRUE only when the condition choice == i and only then should the pop() be initiated.



I have tried the above code without the pop() method in the code and the code works just fine, generating random cards after every run.










share|improve this question
















I am trying to randomly iterate over a deck of cards with no repetition.



Following is the code:



import random

class Cards:

# Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
12: 'dQueen', 13: 'dKing', 14: 'dAce'},
{2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
12: 'hQueen', 13: 'hKing', 14: 'hAce'},
{2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
12: 'sQueen', 13: 'sKing', 14: 'sAce'},
{2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
12: 'cQueen', 13: 'cKing', 14: 'cAce'}]

def random_pick(self): # Method to randomly pick a card from the deck

choice = random.choice(random.choice(self.total_cards))

for v in self.total_cards: # to retrieve the corresponding `key` for `choice`
for i in v.values():
if choice == i:
k = v[i]
v.pop(k)

print(choice) # To print the random card picked from the deck
print(self.total_cards) # To print the updated Deck after picking the card


c = Cards()
c.random_pick()


The idea that I am trying to work with is, as soon as the card is picked, it should be removed from the deck.



This is the error :



Traceback (most recent call last):
File "F:/Blackjack/Base/Cards.py", line 30, in <module>
c.random_pick()
File "F:/Blackjack/Base/Cards.py", line 17, in random_pick
choice = random.choice(random.choice(self.total_cards))
File "C:UsersPythonPython37-32librandom.py", line 262, in choice
return seq[i]
KeyError: 0


From my understanding, KeyError is an exception raised when a mapping (dictionary) key is not found in the set of existing keys. But my IF LOOP is TRUE only when the condition choice == i and only then should the pop() be initiated.



I have tried the above code without the pop() method in the code and the code works just fine, generating random cards after every run.







python python-3.x






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 24 '18 at 10:11









Isma

8,10242136




8,10242136










asked Nov 24 '18 at 10:02









404 Brain Not Found404 Brain Not Found

406115




406115








  • 2





    It's way easier to shuffle the deck instead, like you do in a real card game.

    – user2357112
    Nov 24 '18 at 10:15











  • Why don't you store all the cards in an array and then simply shuffle the array using random.shuffle(array)? Traversal over the shuffled array will be same as randomly iterating over array. Is there any specific reason you want to go for this data-structure?

    – Lavish Kothari
    Nov 24 '18 at 10:26











  • @LavishKothari hi, i know that arrays would do the trick but i am trying to teach myself OOP with DS with an example. Its not mandatory to use DS but that's the goal i started with.

    – 404 Brain Not Found
    Nov 24 '18 at 10:35











  • @user2357112 but that still presents a possibility that an already used card might still reappear. I have to be able to remove the card once it is used

    – 404 Brain Not Found
    Nov 24 '18 at 10:37













  • @404BrainNotFound: Shuffle a list, then draw cards off the end with pop(), or iterate with for. No repetition.

    – user2357112
    Nov 24 '18 at 10:59














  • 2





    It's way easier to shuffle the deck instead, like you do in a real card game.

    – user2357112
    Nov 24 '18 at 10:15











  • Why don't you store all the cards in an array and then simply shuffle the array using random.shuffle(array)? Traversal over the shuffled array will be same as randomly iterating over array. Is there any specific reason you want to go for this data-structure?

    – Lavish Kothari
    Nov 24 '18 at 10:26











  • @LavishKothari hi, i know that arrays would do the trick but i am trying to teach myself OOP with DS with an example. Its not mandatory to use DS but that's the goal i started with.

    – 404 Brain Not Found
    Nov 24 '18 at 10:35











  • @user2357112 but that still presents a possibility that an already used card might still reappear. I have to be able to remove the card once it is used

    – 404 Brain Not Found
    Nov 24 '18 at 10:37













  • @404BrainNotFound: Shuffle a list, then draw cards off the end with pop(), or iterate with for. No repetition.

    – user2357112
    Nov 24 '18 at 10:59








2




2





It's way easier to shuffle the deck instead, like you do in a real card game.

– user2357112
Nov 24 '18 at 10:15





It's way easier to shuffle the deck instead, like you do in a real card game.

– user2357112
Nov 24 '18 at 10:15













Why don't you store all the cards in an array and then simply shuffle the array using random.shuffle(array)? Traversal over the shuffled array will be same as randomly iterating over array. Is there any specific reason you want to go for this data-structure?

– Lavish Kothari
Nov 24 '18 at 10:26





Why don't you store all the cards in an array and then simply shuffle the array using random.shuffle(array)? Traversal over the shuffled array will be same as randomly iterating over array. Is there any specific reason you want to go for this data-structure?

– Lavish Kothari
Nov 24 '18 at 10:26













@LavishKothari hi, i know that arrays would do the trick but i am trying to teach myself OOP with DS with an example. Its not mandatory to use DS but that's the goal i started with.

– 404 Brain Not Found
Nov 24 '18 at 10:35





@LavishKothari hi, i know that arrays would do the trick but i am trying to teach myself OOP with DS with an example. Its not mandatory to use DS but that's the goal i started with.

– 404 Brain Not Found
Nov 24 '18 at 10:35













@user2357112 but that still presents a possibility that an already used card might still reappear. I have to be able to remove the card once it is used

– 404 Brain Not Found
Nov 24 '18 at 10:37







@user2357112 but that still presents a possibility that an already used card might still reappear. I have to be able to remove the card once it is used

– 404 Brain Not Found
Nov 24 '18 at 10:37















@404BrainNotFound: Shuffle a list, then draw cards off the end with pop(), or iterate with for. No repetition.

– user2357112
Nov 24 '18 at 10:59





@404BrainNotFound: Shuffle a list, then draw cards off the end with pop(), or iterate with for. No repetition.

– user2357112
Nov 24 '18 at 10:59












4 Answers
4






active

oldest

votes


















3














If you try your code several times, you'll notice that you won't get this error every time. Sometimes it'll get past the line



        choice = random.choice(random.choice(self.total_cards))


and hit another error later in the code.



So what's going on? I assume that random.choice(self.total_cards) works fine and returns one of the four decks from the total_cards list. You represent that deck as a dictionary.



Let's see what random.choice does with dictionaries on a simpler example:



>>> import random
>>>
>>> random.seed(0) # for reproducability
>>> random.choice({1:2, 3:4})
2


Huh, strange, it returned one of the values. I'd have expected one of the keys, like when iterating over a dictionary without calling .items() nor .values().



>>> [i for i in {1:2, 3:4}]
[1, 3]


Let's try again:



>>> random.seed(42)  # for reproducability
>>> random.choice({1:2, 3:4})
KeyError: 0


Strange, isn't it? 0 is neither among the values nor among the keys here. Where did it come from?



Let's see how random.choice is implemented. In IPython I can get its source code like this:



In [1]: import random

In [2]: random.choice??


To get the code on your system, you can also look at the file mentioned in the error message you got: C:UsersPythonPython37-32librandom.py around line 262.



On Python 3.6.6 (the version on my system) the source code is:



    def choice(self, seq):
"""Choose a random element from a non-empty sequence."""
try:
i = self._randbelow(len(seq))
except ValueError:
raise IndexError('Cannot choose from an empty sequence') from None
return seq[i]


private method random._randbelow has the description




Return a random int in the range [0,n). Raises ValueError if n==0.




While this works fine for sequences (like lists, sets or tuples), I guess you can see why it won't do the right thing at all when seq happens to be a dictionary (or any other mapping):



It takes




the length of the sequence (len(seq))




(which works fine for dictionaries, too) and then




generates a random integer between 0 (inclusive) and that length (exclusive) (that's what self._randbelow does)




so this will be the




0-indexed position of a random element of the sequence




and then it




uses that random integer to index the sequence (seq[i]) and returns that value (return)




which doesn't work on dictionaries as intended because they are




indexed by their keys.




That's also why we sometimes didn't get the error and instead one of the dictionary values was returned by random.choice: When the integer intended as a




random position




also happened to be one of the keys of the dictionary, it would just return the corresponding value. If it happens to be none of our keys (which b.t.w. would always be the case, if all the keys were non-integers, e.g. strings) then a KeyError occurs.






share|improve this answer





















  • 1





    I would add also a sentence like "Look in File "C:UsersPythonPython37-32librandom.py", line 262, as python itself is implicitly suggesting you, to see source code of python 3.7"

    – myfirstAnswer
    Nov 24 '18 at 11:15











  • Good idea @myfirstAnswer. Done.

    – das-g
    Nov 24 '18 at 11:18











  • I also looked at source code and tried to write some answer like yours, but you were faster! so I abandoned my answer :) Good answer!

    – myfirstAnswer
    Nov 24 '18 at 11:21



















1














Quick answer: random.choice() is meant for sequences i.e. lists, as it says in documentation.



Long answer: See das-g's answer.






share|improve this answer


























  • Well, for a novice, it might not be obvious that dictionaries aren't sequences. But +1 for referring to the documentation!

    – das-g
    Nov 24 '18 at 11:23











  • haha :D, thanks!

    – myfirstAnswer
    Nov 24 '18 at 11:29



















0














I think a list would be better, here is how I would do it:



from random import shuffle

class Cards:

def __init__(self): #example deck with just some cards
self.total_cards = ['c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10']
shuffle(self.total_cards) #shuffle the deck of cards

def random_pick(self): #Method to randomly pick a card from the deck

print(self.total_cards[len(self.total_cards)-1]) #To print the last card from your deck, which will be removed by pop() command
self.total_cards.pop()
print(self.total_cards) #To print the updated Deck after pop() the last card


c = Cards()
for _ in range(3): # picking 3 random cards for demostration
c.random_pick()





share|improve this answer





















  • 1





    You don't need to shuffle the deck every time. Shuffling it once up front is enough.

    – user2357112
    Nov 24 '18 at 11:11











  • True, maybe i could put it in the constructor, thanks for the tip

    – redgermany
    Nov 24 '18 at 11:14



















0














Try my solution:



import random
import numpy as np

class Cards:

# Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
12: 'dQueen', 13: 'dKing', 14: 'dAce'},
{2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
12: 'hQueen', 13: 'hKing', 14: 'hAce'},
{2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
12: 'sQueen', 13: 'sKing', 14: 'sAce'},
{2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
12: 'cQueen', 13: 'cKing', 14: 'cAce'}]
_showed = 0

def __init__(self):
self._shuffle_cards()
self.pointers = [0 for _ in range(len(self.total_cards))]

def _shuffle_cards(self):
for i, v in enumerate(self.total_cards):
temp = list(v.items())
self._showed += 1
np.random.shuffle(temp)
self.total_cards[i] = temp

def random_pick(self):
choice = random.choice(range(len(self.total_cards)))
while self.pointers[choice] >= len(self.total_cards[choice]) and self._showed > 0:
choice = random.choice(self.total_cards)
self.pointers[choice] += 1
if self._showed == 0:
print('Nothing cards to show')
else:
self._showed -= 1
print(self.total_cards[choice][self.pointers[choice]][1])


c = Cards()
c.random_pick()





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53457064%2frandom-iteration-over-a-deck-of-cards%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    If you try your code several times, you'll notice that you won't get this error every time. Sometimes it'll get past the line



            choice = random.choice(random.choice(self.total_cards))


    and hit another error later in the code.



    So what's going on? I assume that random.choice(self.total_cards) works fine and returns one of the four decks from the total_cards list. You represent that deck as a dictionary.



    Let's see what random.choice does with dictionaries on a simpler example:



    >>> import random
    >>>
    >>> random.seed(0) # for reproducability
    >>> random.choice({1:2, 3:4})
    2


    Huh, strange, it returned one of the values. I'd have expected one of the keys, like when iterating over a dictionary without calling .items() nor .values().



    >>> [i for i in {1:2, 3:4}]
    [1, 3]


    Let's try again:



    >>> random.seed(42)  # for reproducability
    >>> random.choice({1:2, 3:4})
    KeyError: 0


    Strange, isn't it? 0 is neither among the values nor among the keys here. Where did it come from?



    Let's see how random.choice is implemented. In IPython I can get its source code like this:



    In [1]: import random

    In [2]: random.choice??


    To get the code on your system, you can also look at the file mentioned in the error message you got: C:UsersPythonPython37-32librandom.py around line 262.



    On Python 3.6.6 (the version on my system) the source code is:



        def choice(self, seq):
    """Choose a random element from a non-empty sequence."""
    try:
    i = self._randbelow(len(seq))
    except ValueError:
    raise IndexError('Cannot choose from an empty sequence') from None
    return seq[i]


    private method random._randbelow has the description




    Return a random int in the range [0,n). Raises ValueError if n==0.




    While this works fine for sequences (like lists, sets or tuples), I guess you can see why it won't do the right thing at all when seq happens to be a dictionary (or any other mapping):



    It takes




    the length of the sequence (len(seq))




    (which works fine for dictionaries, too) and then




    generates a random integer between 0 (inclusive) and that length (exclusive) (that's what self._randbelow does)




    so this will be the




    0-indexed position of a random element of the sequence




    and then it




    uses that random integer to index the sequence (seq[i]) and returns that value (return)




    which doesn't work on dictionaries as intended because they are




    indexed by their keys.




    That's also why we sometimes didn't get the error and instead one of the dictionary values was returned by random.choice: When the integer intended as a




    random position




    also happened to be one of the keys of the dictionary, it would just return the corresponding value. If it happens to be none of our keys (which b.t.w. would always be the case, if all the keys were non-integers, e.g. strings) then a KeyError occurs.






    share|improve this answer





















    • 1





      I would add also a sentence like "Look in File "C:UsersPythonPython37-32librandom.py", line 262, as python itself is implicitly suggesting you, to see source code of python 3.7"

      – myfirstAnswer
      Nov 24 '18 at 11:15











    • Good idea @myfirstAnswer. Done.

      – das-g
      Nov 24 '18 at 11:18











    • I also looked at source code and tried to write some answer like yours, but you were faster! so I abandoned my answer :) Good answer!

      – myfirstAnswer
      Nov 24 '18 at 11:21
















    3














    If you try your code several times, you'll notice that you won't get this error every time. Sometimes it'll get past the line



            choice = random.choice(random.choice(self.total_cards))


    and hit another error later in the code.



    So what's going on? I assume that random.choice(self.total_cards) works fine and returns one of the four decks from the total_cards list. You represent that deck as a dictionary.



    Let's see what random.choice does with dictionaries on a simpler example:



    >>> import random
    >>>
    >>> random.seed(0) # for reproducability
    >>> random.choice({1:2, 3:4})
    2


    Huh, strange, it returned one of the values. I'd have expected one of the keys, like when iterating over a dictionary without calling .items() nor .values().



    >>> [i for i in {1:2, 3:4}]
    [1, 3]


    Let's try again:



    >>> random.seed(42)  # for reproducability
    >>> random.choice({1:2, 3:4})
    KeyError: 0


    Strange, isn't it? 0 is neither among the values nor among the keys here. Where did it come from?



    Let's see how random.choice is implemented. In IPython I can get its source code like this:



    In [1]: import random

    In [2]: random.choice??


    To get the code on your system, you can also look at the file mentioned in the error message you got: C:UsersPythonPython37-32librandom.py around line 262.



    On Python 3.6.6 (the version on my system) the source code is:



        def choice(self, seq):
    """Choose a random element from a non-empty sequence."""
    try:
    i = self._randbelow(len(seq))
    except ValueError:
    raise IndexError('Cannot choose from an empty sequence') from None
    return seq[i]


    private method random._randbelow has the description




    Return a random int in the range [0,n). Raises ValueError if n==0.




    While this works fine for sequences (like lists, sets or tuples), I guess you can see why it won't do the right thing at all when seq happens to be a dictionary (or any other mapping):



    It takes




    the length of the sequence (len(seq))




    (which works fine for dictionaries, too) and then




    generates a random integer between 0 (inclusive) and that length (exclusive) (that's what self._randbelow does)




    so this will be the




    0-indexed position of a random element of the sequence




    and then it




    uses that random integer to index the sequence (seq[i]) and returns that value (return)




    which doesn't work on dictionaries as intended because they are




    indexed by their keys.




    That's also why we sometimes didn't get the error and instead one of the dictionary values was returned by random.choice: When the integer intended as a




    random position




    also happened to be one of the keys of the dictionary, it would just return the corresponding value. If it happens to be none of our keys (which b.t.w. would always be the case, if all the keys were non-integers, e.g. strings) then a KeyError occurs.






    share|improve this answer





















    • 1





      I would add also a sentence like "Look in File "C:UsersPythonPython37-32librandom.py", line 262, as python itself is implicitly suggesting you, to see source code of python 3.7"

      – myfirstAnswer
      Nov 24 '18 at 11:15











    • Good idea @myfirstAnswer. Done.

      – das-g
      Nov 24 '18 at 11:18











    • I also looked at source code and tried to write some answer like yours, but you were faster! so I abandoned my answer :) Good answer!

      – myfirstAnswer
      Nov 24 '18 at 11:21














    3












    3








    3







    If you try your code several times, you'll notice that you won't get this error every time. Sometimes it'll get past the line



            choice = random.choice(random.choice(self.total_cards))


    and hit another error later in the code.



    So what's going on? I assume that random.choice(self.total_cards) works fine and returns one of the four decks from the total_cards list. You represent that deck as a dictionary.



    Let's see what random.choice does with dictionaries on a simpler example:



    >>> import random
    >>>
    >>> random.seed(0) # for reproducability
    >>> random.choice({1:2, 3:4})
    2


    Huh, strange, it returned one of the values. I'd have expected one of the keys, like when iterating over a dictionary without calling .items() nor .values().



    >>> [i for i in {1:2, 3:4}]
    [1, 3]


    Let's try again:



    >>> random.seed(42)  # for reproducability
    >>> random.choice({1:2, 3:4})
    KeyError: 0


    Strange, isn't it? 0 is neither among the values nor among the keys here. Where did it come from?



    Let's see how random.choice is implemented. In IPython I can get its source code like this:



    In [1]: import random

    In [2]: random.choice??


    To get the code on your system, you can also look at the file mentioned in the error message you got: C:UsersPythonPython37-32librandom.py around line 262.



    On Python 3.6.6 (the version on my system) the source code is:



        def choice(self, seq):
    """Choose a random element from a non-empty sequence."""
    try:
    i = self._randbelow(len(seq))
    except ValueError:
    raise IndexError('Cannot choose from an empty sequence') from None
    return seq[i]


    private method random._randbelow has the description




    Return a random int in the range [0,n). Raises ValueError if n==0.




    While this works fine for sequences (like lists, sets or tuples), I guess you can see why it won't do the right thing at all when seq happens to be a dictionary (or any other mapping):



    It takes




    the length of the sequence (len(seq))




    (which works fine for dictionaries, too) and then




    generates a random integer between 0 (inclusive) and that length (exclusive) (that's what self._randbelow does)




    so this will be the




    0-indexed position of a random element of the sequence




    and then it




    uses that random integer to index the sequence (seq[i]) and returns that value (return)




    which doesn't work on dictionaries as intended because they are




    indexed by their keys.




    That's also why we sometimes didn't get the error and instead one of the dictionary values was returned by random.choice: When the integer intended as a




    random position




    also happened to be one of the keys of the dictionary, it would just return the corresponding value. If it happens to be none of our keys (which b.t.w. would always be the case, if all the keys were non-integers, e.g. strings) then a KeyError occurs.






    share|improve this answer















    If you try your code several times, you'll notice that you won't get this error every time. Sometimes it'll get past the line



            choice = random.choice(random.choice(self.total_cards))


    and hit another error later in the code.



    So what's going on? I assume that random.choice(self.total_cards) works fine and returns one of the four decks from the total_cards list. You represent that deck as a dictionary.



    Let's see what random.choice does with dictionaries on a simpler example:



    >>> import random
    >>>
    >>> random.seed(0) # for reproducability
    >>> random.choice({1:2, 3:4})
    2


    Huh, strange, it returned one of the values. I'd have expected one of the keys, like when iterating over a dictionary without calling .items() nor .values().



    >>> [i for i in {1:2, 3:4}]
    [1, 3]


    Let's try again:



    >>> random.seed(42)  # for reproducability
    >>> random.choice({1:2, 3:4})
    KeyError: 0


    Strange, isn't it? 0 is neither among the values nor among the keys here. Where did it come from?



    Let's see how random.choice is implemented. In IPython I can get its source code like this:



    In [1]: import random

    In [2]: random.choice??


    To get the code on your system, you can also look at the file mentioned in the error message you got: C:UsersPythonPython37-32librandom.py around line 262.



    On Python 3.6.6 (the version on my system) the source code is:



        def choice(self, seq):
    """Choose a random element from a non-empty sequence."""
    try:
    i = self._randbelow(len(seq))
    except ValueError:
    raise IndexError('Cannot choose from an empty sequence') from None
    return seq[i]


    private method random._randbelow has the description




    Return a random int in the range [0,n). Raises ValueError if n==0.




    While this works fine for sequences (like lists, sets or tuples), I guess you can see why it won't do the right thing at all when seq happens to be a dictionary (or any other mapping):



    It takes




    the length of the sequence (len(seq))




    (which works fine for dictionaries, too) and then




    generates a random integer between 0 (inclusive) and that length (exclusive) (that's what self._randbelow does)




    so this will be the




    0-indexed position of a random element of the sequence




    and then it




    uses that random integer to index the sequence (seq[i]) and returns that value (return)




    which doesn't work on dictionaries as intended because they are




    indexed by their keys.




    That's also why we sometimes didn't get the error and instead one of the dictionary values was returned by random.choice: When the integer intended as a




    random position




    also happened to be one of the keys of the dictionary, it would just return the corresponding value. If it happens to be none of our keys (which b.t.w. would always be the case, if all the keys were non-integers, e.g. strings) then a KeyError occurs.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 24 '18 at 11:36

























    answered Nov 24 '18 at 11:09









    das-gdas-g

    5,98522353




    5,98522353








    • 1





      I would add also a sentence like "Look in File "C:UsersPythonPython37-32librandom.py", line 262, as python itself is implicitly suggesting you, to see source code of python 3.7"

      – myfirstAnswer
      Nov 24 '18 at 11:15











    • Good idea @myfirstAnswer. Done.

      – das-g
      Nov 24 '18 at 11:18











    • I also looked at source code and tried to write some answer like yours, but you were faster! so I abandoned my answer :) Good answer!

      – myfirstAnswer
      Nov 24 '18 at 11:21














    • 1





      I would add also a sentence like "Look in File "C:UsersPythonPython37-32librandom.py", line 262, as python itself is implicitly suggesting you, to see source code of python 3.7"

      – myfirstAnswer
      Nov 24 '18 at 11:15











    • Good idea @myfirstAnswer. Done.

      – das-g
      Nov 24 '18 at 11:18











    • I also looked at source code and tried to write some answer like yours, but you were faster! so I abandoned my answer :) Good answer!

      – myfirstAnswer
      Nov 24 '18 at 11:21








    1




    1





    I would add also a sentence like "Look in File "C:UsersPythonPython37-32librandom.py", line 262, as python itself is implicitly suggesting you, to see source code of python 3.7"

    – myfirstAnswer
    Nov 24 '18 at 11:15





    I would add also a sentence like "Look in File "C:UsersPythonPython37-32librandom.py", line 262, as python itself is implicitly suggesting you, to see source code of python 3.7"

    – myfirstAnswer
    Nov 24 '18 at 11:15













    Good idea @myfirstAnswer. Done.

    – das-g
    Nov 24 '18 at 11:18





    Good idea @myfirstAnswer. Done.

    – das-g
    Nov 24 '18 at 11:18













    I also looked at source code and tried to write some answer like yours, but you were faster! so I abandoned my answer :) Good answer!

    – myfirstAnswer
    Nov 24 '18 at 11:21





    I also looked at source code and tried to write some answer like yours, but you were faster! so I abandoned my answer :) Good answer!

    – myfirstAnswer
    Nov 24 '18 at 11:21













    1














    Quick answer: random.choice() is meant for sequences i.e. lists, as it says in documentation.



    Long answer: See das-g's answer.






    share|improve this answer


























    • Well, for a novice, it might not be obvious that dictionaries aren't sequences. But +1 for referring to the documentation!

      – das-g
      Nov 24 '18 at 11:23











    • haha :D, thanks!

      – myfirstAnswer
      Nov 24 '18 at 11:29
















    1














    Quick answer: random.choice() is meant for sequences i.e. lists, as it says in documentation.



    Long answer: See das-g's answer.






    share|improve this answer


























    • Well, for a novice, it might not be obvious that dictionaries aren't sequences. But +1 for referring to the documentation!

      – das-g
      Nov 24 '18 at 11:23











    • haha :D, thanks!

      – myfirstAnswer
      Nov 24 '18 at 11:29














    1












    1








    1







    Quick answer: random.choice() is meant for sequences i.e. lists, as it says in documentation.



    Long answer: See das-g's answer.






    share|improve this answer















    Quick answer: random.choice() is meant for sequences i.e. lists, as it says in documentation.



    Long answer: See das-g's answer.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 24 '18 at 11:24









    das-g

    5,98522353




    5,98522353










    answered Nov 24 '18 at 11:17









    myfirstAnswermyfirstAnswer

    30134




    30134













    • Well, for a novice, it might not be obvious that dictionaries aren't sequences. But +1 for referring to the documentation!

      – das-g
      Nov 24 '18 at 11:23











    • haha :D, thanks!

      – myfirstAnswer
      Nov 24 '18 at 11:29



















    • Well, for a novice, it might not be obvious that dictionaries aren't sequences. But +1 for referring to the documentation!

      – das-g
      Nov 24 '18 at 11:23











    • haha :D, thanks!

      – myfirstAnswer
      Nov 24 '18 at 11:29

















    Well, for a novice, it might not be obvious that dictionaries aren't sequences. But +1 for referring to the documentation!

    – das-g
    Nov 24 '18 at 11:23





    Well, for a novice, it might not be obvious that dictionaries aren't sequences. But +1 for referring to the documentation!

    – das-g
    Nov 24 '18 at 11:23













    haha :D, thanks!

    – myfirstAnswer
    Nov 24 '18 at 11:29





    haha :D, thanks!

    – myfirstAnswer
    Nov 24 '18 at 11:29











    0














    I think a list would be better, here is how I would do it:



    from random import shuffle

    class Cards:

    def __init__(self): #example deck with just some cards
    self.total_cards = ['c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10']
    shuffle(self.total_cards) #shuffle the deck of cards

    def random_pick(self): #Method to randomly pick a card from the deck

    print(self.total_cards[len(self.total_cards)-1]) #To print the last card from your deck, which will be removed by pop() command
    self.total_cards.pop()
    print(self.total_cards) #To print the updated Deck after pop() the last card


    c = Cards()
    for _ in range(3): # picking 3 random cards for demostration
    c.random_pick()





    share|improve this answer





















    • 1





      You don't need to shuffle the deck every time. Shuffling it once up front is enough.

      – user2357112
      Nov 24 '18 at 11:11











    • True, maybe i could put it in the constructor, thanks for the tip

      – redgermany
      Nov 24 '18 at 11:14
















    0














    I think a list would be better, here is how I would do it:



    from random import shuffle

    class Cards:

    def __init__(self): #example deck with just some cards
    self.total_cards = ['c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10']
    shuffle(self.total_cards) #shuffle the deck of cards

    def random_pick(self): #Method to randomly pick a card from the deck

    print(self.total_cards[len(self.total_cards)-1]) #To print the last card from your deck, which will be removed by pop() command
    self.total_cards.pop()
    print(self.total_cards) #To print the updated Deck after pop() the last card


    c = Cards()
    for _ in range(3): # picking 3 random cards for demostration
    c.random_pick()





    share|improve this answer





















    • 1





      You don't need to shuffle the deck every time. Shuffling it once up front is enough.

      – user2357112
      Nov 24 '18 at 11:11











    • True, maybe i could put it in the constructor, thanks for the tip

      – redgermany
      Nov 24 '18 at 11:14














    0












    0








    0







    I think a list would be better, here is how I would do it:



    from random import shuffle

    class Cards:

    def __init__(self): #example deck with just some cards
    self.total_cards = ['c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10']
    shuffle(self.total_cards) #shuffle the deck of cards

    def random_pick(self): #Method to randomly pick a card from the deck

    print(self.total_cards[len(self.total_cards)-1]) #To print the last card from your deck, which will be removed by pop() command
    self.total_cards.pop()
    print(self.total_cards) #To print the updated Deck after pop() the last card


    c = Cards()
    for _ in range(3): # picking 3 random cards for demostration
    c.random_pick()





    share|improve this answer















    I think a list would be better, here is how I would do it:



    from random import shuffle

    class Cards:

    def __init__(self): #example deck with just some cards
    self.total_cards = ['c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10']
    shuffle(self.total_cards) #shuffle the deck of cards

    def random_pick(self): #Method to randomly pick a card from the deck

    print(self.total_cards[len(self.total_cards)-1]) #To print the last card from your deck, which will be removed by pop() command
    self.total_cards.pop()
    print(self.total_cards) #To print the updated Deck after pop() the last card


    c = Cards()
    for _ in range(3): # picking 3 random cards for demostration
    c.random_pick()






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 24 '18 at 11:17

























    answered Nov 24 '18 at 11:10









    redgermanyredgermany

    235




    235








    • 1





      You don't need to shuffle the deck every time. Shuffling it once up front is enough.

      – user2357112
      Nov 24 '18 at 11:11











    • True, maybe i could put it in the constructor, thanks for the tip

      – redgermany
      Nov 24 '18 at 11:14














    • 1





      You don't need to shuffle the deck every time. Shuffling it once up front is enough.

      – user2357112
      Nov 24 '18 at 11:11











    • True, maybe i could put it in the constructor, thanks for the tip

      – redgermany
      Nov 24 '18 at 11:14








    1




    1





    You don't need to shuffle the deck every time. Shuffling it once up front is enough.

    – user2357112
    Nov 24 '18 at 11:11





    You don't need to shuffle the deck every time. Shuffling it once up front is enough.

    – user2357112
    Nov 24 '18 at 11:11













    True, maybe i could put it in the constructor, thanks for the tip

    – redgermany
    Nov 24 '18 at 11:14





    True, maybe i could put it in the constructor, thanks for the tip

    – redgermany
    Nov 24 '18 at 11:14











    0














    Try my solution:



    import random
    import numpy as np

    class Cards:

    # Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
    total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
    12: 'dQueen', 13: 'dKing', 14: 'dAce'},
    {2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
    12: 'hQueen', 13: 'hKing', 14: 'hAce'},
    {2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
    12: 'sQueen', 13: 'sKing', 14: 'sAce'},
    {2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
    12: 'cQueen', 13: 'cKing', 14: 'cAce'}]
    _showed = 0

    def __init__(self):
    self._shuffle_cards()
    self.pointers = [0 for _ in range(len(self.total_cards))]

    def _shuffle_cards(self):
    for i, v in enumerate(self.total_cards):
    temp = list(v.items())
    self._showed += 1
    np.random.shuffle(temp)
    self.total_cards[i] = temp

    def random_pick(self):
    choice = random.choice(range(len(self.total_cards)))
    while self.pointers[choice] >= len(self.total_cards[choice]) and self._showed > 0:
    choice = random.choice(self.total_cards)
    self.pointers[choice] += 1
    if self._showed == 0:
    print('Nothing cards to show')
    else:
    self._showed -= 1
    print(self.total_cards[choice][self.pointers[choice]][1])


    c = Cards()
    c.random_pick()





    share|improve this answer




























      0














      Try my solution:



      import random
      import numpy as np

      class Cards:

      # Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
      total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
      12: 'dQueen', 13: 'dKing', 14: 'dAce'},
      {2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
      12: 'hQueen', 13: 'hKing', 14: 'hAce'},
      {2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
      12: 'sQueen', 13: 'sKing', 14: 'sAce'},
      {2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
      12: 'cQueen', 13: 'cKing', 14: 'cAce'}]
      _showed = 0

      def __init__(self):
      self._shuffle_cards()
      self.pointers = [0 for _ in range(len(self.total_cards))]

      def _shuffle_cards(self):
      for i, v in enumerate(self.total_cards):
      temp = list(v.items())
      self._showed += 1
      np.random.shuffle(temp)
      self.total_cards[i] = temp

      def random_pick(self):
      choice = random.choice(range(len(self.total_cards)))
      while self.pointers[choice] >= len(self.total_cards[choice]) and self._showed > 0:
      choice = random.choice(self.total_cards)
      self.pointers[choice] += 1
      if self._showed == 0:
      print('Nothing cards to show')
      else:
      self._showed -= 1
      print(self.total_cards[choice][self.pointers[choice]][1])


      c = Cards()
      c.random_pick()





      share|improve this answer


























        0












        0








        0







        Try my solution:



        import random
        import numpy as np

        class Cards:

        # Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
        total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
        12: 'dQueen', 13: 'dKing', 14: 'dAce'},
        {2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
        12: 'hQueen', 13: 'hKing', 14: 'hAce'},
        {2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
        12: 'sQueen', 13: 'sKing', 14: 'sAce'},
        {2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
        12: 'cQueen', 13: 'cKing', 14: 'cAce'}]
        _showed = 0

        def __init__(self):
        self._shuffle_cards()
        self.pointers = [0 for _ in range(len(self.total_cards))]

        def _shuffle_cards(self):
        for i, v in enumerate(self.total_cards):
        temp = list(v.items())
        self._showed += 1
        np.random.shuffle(temp)
        self.total_cards[i] = temp

        def random_pick(self):
        choice = random.choice(range(len(self.total_cards)))
        while self.pointers[choice] >= len(self.total_cards[choice]) and self._showed > 0:
        choice = random.choice(self.total_cards)
        self.pointers[choice] += 1
        if self._showed == 0:
        print('Nothing cards to show')
        else:
        self._showed -= 1
        print(self.total_cards[choice][self.pointers[choice]][1])


        c = Cards()
        c.random_pick()





        share|improve this answer













        Try my solution:



        import random
        import numpy as np

        class Cards:

        # Where prefix d is Diamonds, h is Hearts, s is Spades and c is Clubs
        total_cards = [{2: 'd2', 3: 'd3', 4: 'd4', 5: 'd5', 6: 'd6', 7: 'd7', 8: 'd8', 9: 'd9', 10: 'd10', 11: 'dJack',
        12: 'dQueen', 13: 'dKing', 14: 'dAce'},
        {2: 'h2', 3: 'h3', 4: 'h4', 5: 'h5', 6: 'h6', 7: 'h7', 8: 'h8', 9: 'h9', 10: 'h10', 11: 'hJack',
        12: 'hQueen', 13: 'hKing', 14: 'hAce'},
        {2: 's2', 3: 's3', 4: 's4', 5: 's5', 6: 's6', 7: 's7', 8: 's8', 9: 's9', 10: 's10', 11: 'sJack',
        12: 'sQueen', 13: 'sKing', 14: 'sAce'},
        {2: 'c2', 3: 'c3', 4: 'c4', 5: 'c5', 6: 'c6', 7: 'c7', 8: 'c8', 9: 'c9', 10: 'c10', 11: 'cJack',
        12: 'cQueen', 13: 'cKing', 14: 'cAce'}]
        _showed = 0

        def __init__(self):
        self._shuffle_cards()
        self.pointers = [0 for _ in range(len(self.total_cards))]

        def _shuffle_cards(self):
        for i, v in enumerate(self.total_cards):
        temp = list(v.items())
        self._showed += 1
        np.random.shuffle(temp)
        self.total_cards[i] = temp

        def random_pick(self):
        choice = random.choice(range(len(self.total_cards)))
        while self.pointers[choice] >= len(self.total_cards[choice]) and self._showed > 0:
        choice = random.choice(self.total_cards)
        self.pointers[choice] += 1
        if self._showed == 0:
        print('Nothing cards to show')
        else:
        self._showed -= 1
        print(self.total_cards[choice][self.pointers[choice]][1])


        c = Cards()
        c.random_pick()






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 24 '18 at 11:25









        Alexey S. KiselevAlexey S. Kiselev

        1046




        1046






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53457064%2frandom-iteration-over-a-deck-of-cards%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Wiesbaden

            Marschland

            Dieringhausen