2017 GCSE纸牌魔术代码出现“Pop from empty list” IndexError问题排查
Fixing the "Pop from empty list" IndexError in your GCSE Card Trick Python Code
Let's break down what's causing that frustrating error and fix it step by step.
The Root Cause
Looking at your create_piles function, I spot a critical variable mix-up that's triggering the error:
def create_piles(deck): pile1 = [] pile2 = [] pile3 = [] for i in range(7): pile1.append(cards.pop()) # ❌ Using 'cards' instead of the passed 'deck' parameter pile2.append(cards.pop()) pile3.append(cards.pop())
You’ve defined the function to accept a deck parameter, but inside the loop, you’re trying to pop from cards instead. Here’s why this leads to an empty list error:
- If
cardsis a global variable that’s already been emptied (e.g., from a previous test run), callingpop()on it will throw the IndexError. - Even if
cardsexists, you’re ignoring thedeckargument passed to the function—which is likely the actual 21-card deck you created withcreate_deck().
Fixed Full Code
Here’s the corrected version with clear explanations of the changes:
import random def create_deck(): suits = ["♥","♣","♦","♠"] values = ["1","2","3","4","5","6","7","8","9","10","J","Q","K"] deck = [] for suit in suits: for value in values: card = value + suit deck.append(card) # Shuffling once is sufficient, but twice won't break anything random.shuffle(deck) random.shuffle(deck) selected_cards = deck[:21] print("Created 21-card deck:", selected_cards) return selected_cards def create_piles(deck): pile1 = [] pile2 = [] pile3 = [] for i in range(7): # Use the 'deck' parameter instead of 'cards' to pop from the correct list pile1.append(deck.pop()) pile2.append(deck.pop()) pile3.append(deck.pop()) # Added print statements to verify piles are correctly built print("Pile 1:", pile1) print("Pile 2:", pile2) print("Pile 3:", pile3) return pile1, pile2, pile3 # Test the code directly when running the script if __name__ == "__main__": game_deck = create_deck() create_piles(game_deck)
Key Fixes & Notes
- Variable Consistency: We now use the
deckparameter increate_pilesinstead of the misusedcardsvariable, ensuring we always pop from the 21-card deck you passed in. - Clarity: Renamed
cardsincreate_decktoselected_cardsto avoid confusion with other variables in the script. - Testable Structure: Added an
if __name__ == "__main__":block so you can run the script directly to test deck creation and pile splitting. - Guaranteed No Empty List Errors: Since we’re popping exactly 21 times (7 loops × 3 cards per loop) from a 21-card deck, we’ll never try to pop from an empty list again.
Bonus: Preserve the Original Deck
If you don’t want to modify the original deck when creating piles (since pop() removes elements from the list), create a copy first:
def create_piles(deck): deck_copy = deck.copy() # Make a copy so the original deck stays intact pile1 = [] pile2 = [] pile3 = [] for i in range(7): pile1.append(deck_copy.pop()) pile2.append(deck_copy.pop()) pile3.append(deck_copy.pop()) print("Pile 1:", pile1) print("Pile 2:", pile2) print("Pile 3:", pile3) return pile1, pile2, pile3
This way, your original game_deck list remains unchanged after calling create_piles().
内容的提问来源于stack exchange,提问作者I. Abbas
相关产品推荐
相关产品推荐

