Skip to main content
April 2, 2026Brian McClain/4 min read

Nested Loops- Building and Shuffling a Deck of Cards

Master Python loops through practical card programming

Deck Building by the Numbers

52
Total cards in standard deck
13
Different card kinds
4
Card suits
2
Cards dealt to each player initially
Understanding Nested Loops

A nested loop is a loop inside another loop. For card deck creation, the outer loop iterates through 13 kinds while the inner loop processes 4 suits for each kind, resulting in 13 × 4 = 52 total iterations.

Building a Complete Card Deck

1

Create Lists

Define two lists - one for card kinds (Ace through King) and one for suits (clubs, diamonds, hearts, spades)

2

Set Up Nested Loop

Use outer loop for kinds and inner loop for suits to iterate through all combinations

3

Generate Card Names

Use f-string formatting to create card names like 'four of clubs' and append to deck list

4

Shuffle the Deck

Apply random.shuffle() to randomize card order before dealing

Loop Structure Comparison

FeatureSingle LoopNested Loop
Iterations13 or 452
ComplexitySimpleModerate
Use CaseSingle dimensionMultiple dimensions
OutputOne listCombined data
Recommended: Nested loops are essential when you need to process combinations of multiple datasets, like creating all possible card combinations.

Key Programming Concepts

F-string Formatting

Modern Python string formatting using f-strings allows clean variable interpolation. Example: f'{k} of {s}' creates readable card names.

List Methods

deck.append() adds new items to lists while deck.pop() removes and returns the last item, perfect for card dealing simulation.

Modulus Operation

The % operator finds remainders, enabling even-odd alternation for proper card dealing between player and dealer.

Card Dealing Pattern

Player Cards
2
Dealer Cards
2

Blackjack Dealing Implementation

0/4
You shuffle all the cards to make sure they're randomized already. And then you just pick off the top - pop.
This mirrors real-world card dealing where shuffling happens once, then cards are dealt sequentially from the top of the deck.

Using Pop vs Random Selection

Pros
Mimics realistic card dealing behavior
More efficient - no repeated random calculations
Prevents duplicate cards being dealt
Maintains deck integrity throughout game
Cons
Requires initial shuffle step
Modifies original deck list
Less obvious randomness to beginners
Foundation for Data Science

Mastering these programming fundamentals - loops, list manipulation, and modulus operations - provides the essential building blocks needed before diving into data science concepts. Like learning ABCs before writing novels.

Learning Progression Path

Foundation

Master Basic Loops

Single for loops and list iteration

Intermediate

Understand Nested Structures

Loops within loops for complex data processing

Practical

Apply to Real Problems

Card games, data manipulation, file processing

Specialization

Advance to Data Science

Use solid programming base for analytics focus

This lesson is a preview from our Data Science & AI Certificate Online (includes software) and Python Certification Online (includes software & exam). Enroll in a course for detailed lessons, live instructor support, and project-based training.

Now let's explore nested loops—a powerful programming concept where one loop operates inside another. Using two lists as our foundation, we'll construct a complete deck of 52 playing cards, generating strings like "four of clubs" and "queen of diamonds" that represent each unique card combination.

Our goal is to store these 52 card names in a new list called `deck`. While we could extend this concept to generate file names for card images or other assets, we'll focus on creating the fundamental card identifiers—a skill that translates directly to data processing scenarios you'll encounter in professional development.

The foundation requires two carefully structured lists: `kinds` (representing the 13 card values) and `suits` (representing the 4 suit types). This creates a mathematical relationship: 13 kinds multiplied by 4 suits equals exactly 52 iterations. When you iterate over them simultaneously—processing every "two" with all four suits, then every "three" with all four suits—you achieve complete coverage of all possible combinations.

To implement this pattern, we use a nested loop structure. The outer loop `for k in kinds` handles each card value, while the inner loop `for s in suits` processes each suit for the current kind. This nested approach ensures that the suits loop executes completely for every single iteration of the kinds loop—running 13 times total and producing our desired 52 combinations.

The card creation process combines these variables using Python's f-string formatting: `deck.append(f"{k} of {s}")`. This modern string formatting approach provides clean, readable code that's become the industry standard for string interpolation in Python applications.

Building on concepts from previous lessons, we can enhance our deck with randomization. The `random.shuffle()` function, introduced earlier in our series, allows us to randomize the card order—a critical step for any card game simulation. After shuffling, we can display the first five cards to verify our randomization worked correctly.

Let's apply these concepts to a practical scenario: dealing a blackjack hand to two players. This real-world application demonstrates how nested loops and modular arithmetic solve complex distribution problems you'll encounter in data processing and game development.


The dealing algorithm requires careful attention to alternating distribution. In blackjack, cards must be dealt alternately between player and dealer, with each receiving two cards total. We implement this using a `for` loop with range(4) and modulus operations to determine card recipients.

Using `range(10, 14)` instead of `range(4)` simplifies our modulus calculations—working with larger numbers makes even-odd determination more intuitive. When `N % 2 == 0`, we're dealing the first and third cards (N=10 and N=12) to the player. The remaining cards (N=11 and N=13) go to the dealer, maintaining proper dealing protocol.

The `deck.pop()` method removes and returns the top card from our shuffled deck. This mimics real-world dealing mechanics: rather than selecting random cards from the middle of the deck, we shuffle once to randomize order, then deal sequentially from the top. This approach is both more realistic and computationally efficient.

Our card distribution logic uses conditional statements within the loop: `player_hand.append(deck.pop())` for even iterations and `dealer_hand.append(deck.pop())` for odd iterations. Each dealt card is printed immediately, providing visual confirmation that the alternating pattern works correctly.

The final implementation creates separate lists for player and dealer hands, demonstrating how loops can build multiple data structures simultaneously. This pattern appears frequently in data science applications where you need to categorize or distribute information across multiple containers based on specific criteria.

Notice that we're not iterating directly over the card list—instead, we loop over a range of numbers because our primary concern is executing exactly four iterations. The deck exists as an independent data structure that we access via `pop()` operations, maintaining clean separation between our control logic and data storage.


This nested loop approach for deck creation, combined with modulus-based distribution for card dealing, demonstrates fundamental programming patterns that scale to complex data processing scenarios. Whether you're distributing computational tasks, categorizing data records, or implementing game mechanics, these techniques provide reliable, readable solutions.

This lesson covered substantial ground: nested iteration patterns, modular arithmetic applications, and practical list manipulation techniques. These concepts form crucial building blocks for the data science work ahead, where you'll process datasets far more complex than playing cards but using these same fundamental patterns.

Mastering these programming fundamentals now allows you to focus entirely on data science methodologies later, rather than struggling with basic syntax and logic structures. Like learning grammar before writing literature, these foundational skills enable you to tackle sophisticated analytical challenges with confidence.

That concludes lesson four. Take time to practice these nested loop patterns with your own data structures—they're essential tools in every Python developer's toolkit. We'll see you in lesson five when you're ready to advance further.

Key Takeaways

1Nested loops enable processing of multidimensional data by placing one loop inside another, with the inner loop completing all iterations for each outer loop cycle
2Creating a 52-card deck requires iterating through 13 card kinds and 4 suits using nested loops, generating combinations with f-string formatting
3The random.shuffle() function randomizes list order once, eliminating the need for repeated random selection during card dealing
4Modulus operator enables alternating patterns in loops, essential for proper card dealing between multiple players
5Using pop() method simulates realistic card dealing by removing cards from deck top rather than random middle positions
6Separating data preparation (shuffling) from processing (dealing) creates more efficient and realistic program behavior
7Strong programming fundamentals must be mastered before advancing to specialized fields like data science
8List methods like append() and pop() provide essential tools for dynamic data structure manipulation during program execution

RELATED ARTICLES