Embercode
✕
Pattern PrintingLesson 3 of 15

45 min read

Pyramid patterns in Python

Why this matters

A pyramid is the pattern most people picture when they hear the word pattern. It is also the first pattern where each row has two parts that change together. Each row needs spaces on the left to centre it, and then a number of symbols in the middle. If one of those counts is wrong, the whole picture leans to one side, and the mistake is easy to miss on a quick look.

Pyramids are a common interview question because they test a second skill on top of loops. You keep two formulas in mind at once, check that they agree on every row, and then group the code into functions so the main part of the program stays short. A function is a named block of code that you can call by name from anywhere else in the program.

In this lesson you print four kinds of pyramid: a centred star pyramid, an inverted pyramid, a number pyramid and a letter pyramid. Then you move the row code into functions. Every program below was run with Python 3.14, and the output shown is what it printed. To try another size, change the value of n in the program.

If you know Java, the loops look the same. The differences are that range replaces the <= check, print takes an end argument in place of a separate print call, and blocks are marked by indentation instead of curly brackets.

The idea: two parts in every row

Here is a centred pyramid with four rows.

   *
  ***
 *****
*******

Each row has the same total width, which is seven characters, and the stars sit in the middle. Look at one row at a time and ask two questions. How many spaces come before the stars? How many stars are there?

Count the rows from 1 at the top, and call the row number i. The number of stars in row i is 2 * i - 1. Row 1 has 1 star, row 2 has 3, row 3 has 5 and row 4 has 7. The stars go up by two each time, because each row needs one more star on each side of the middle. The number of spaces is n - i, where n is the number of rows. Row 1 has 3 spaces, row 2 has 2, and the spaces go down by one each time.

The bottom row is 2 * n - 1 characters wide, so it sets the width of the whole picture. Every other row is centred on the same middle column. The spaces on the left do all the centring, and no row needs spaces on the right.

This table has one row for each i, when n is 4.

Row iSpaces n - iStars 2 * i - 1
131
223
315
407

Check the first row and the last row before you trust the formulas. Row 1 has 3 spaces and 1 star, and that matches the picture. Row 4 has no spaces and 7 stars, and that also matches. A third check is the total number of stars, which is 1 plus 3 plus 5 plus 7, or 16. For any n, a centred pyramid has n * n stars in total, so 4 rows give 16.

Worked example 1: a centred pyramid

Python's range(a, b) gives the numbers from a up to, but not including, b. So range(3) gives 0, 1 and 2, which is three numbers. The loop for _ in range(n - i): runs n - i times. The name _ is a variable that you do not use. It tells the reader that only the repeat count matters.

The function print(" ", end="") prints one space and does not move to a new line. A plain print() with nothing inside it moves to a new line, and that is how each row ends.

The program below prints a centred pyramid with four rows. It uses two inner loops in each pass of the outer loop. The first prints the spaces, the second prints the stars, and the last print() ends the row.

Python · editable

The output is:

   *
  ***
 *****
*******

Trace row 2. The outer loop sets i to 2. The first inner loop runs n - i, which is 2 times, so it prints two spaces. The second inner loop runs 2 * i - 1, which is 3 times, so it prints three stars. The print() ends the line. Row 2 is two spaces and three stars, which is the second line of the output.

Python can also build the whole row as one string. Multiplying a string by a number repeats it, so "*" * 3 is "***", and " " * 2 is two spaces. Joining the two parts with + gives the row in one line.

Python · editable

The output is the same as before. Both versions teach the same idea, which is that a row has a space part and a symbol part. The loop version shows the counting more clearly, and the string version is shorter. Use the one that is easier for you to check.

Worked example 2: an inverted pyramid

An inverted pyramid is the centred pyramid turned upside down. The widest row comes first, and the single star comes last. The width goes down by two each time, and the spaces go up by one each time.

Use the same counting method as before. Row i has i - 1 spaces and 2 * (n - i) + 1 stars. For n equal to 4, the widest row is row 1, and it has 2 * (4 - 1) + 1, which is 7 stars.

Row iSpaces i - 1Stars 2 * (n - i) + 1
107
215
323
431

Check the last row. It should have one star with three spaces in front. The formula gives 1 star and 3 spaces, so the table is right.

Python · editable

The output is:

*******
 *****
  ***
   *

Compare row 2 with the table. It has one space and five stars, which matches the row for i equal to 2. A second way to write the same picture counts i down from n to 1 and uses the upright formulas. Python can do that with the third argument of range, which is the step. The function range(n, 0, -1) starts at n and goes down by one, stopping before 0. You will see it in the functions example below.

Worked example 3: a number pyramid

A number pyramid has the same centred shape, but the symbols are digits. Row 1 is 1. Row 2 is 121. Row 3 is 12321. Row 4 is 1234321. The digits count up to the row number and then back down to 1.

Each row therefore needs two loops for the digits, one going up and one going down. The first loop prints the numbers 1 to i. The second loop prints the numbers from i - 1 down to 1. The step of -1 in range(i - 1, 0, -1) makes the counter go down. The stop value is 0, which is not included, so the loop ends at 1.

Python · editable

The output is:

   1
  121
 12321
1234321

Trace row 3. The outer loop sets i to 3. The first loop runs n - i, which is 1 time, so it prints one space. The second loop prints 1, 2 and 3. The third loop starts at i - 1, which is 2, and goes down to 1, so it prints 2 and then 1. The row is 12321, with one leading space, which is correct for row 3 of a four-row pyramid.

Python prints each number as text when you give print an integer, so print(d, end="") works without a str call. This changes when a row has a two-digit number. For n equal to 10 the middle of the last row is 10, and the row becomes 12345678910987654321. That is 20 characters, not 19, so the pyramid no longer lines up as neatly. For a tidy number pyramid, keep n at 9 or less, or format each number to a fixed width.

Worked example 4: a letter pyramid

A letter pyramid has the same shape as the number pyramid, but the symbols are letters. Row 1 is A. Row 2 is ABA. Row 3 is ABCBA. Row 4 is ABCDCBA. The letters rise from A to the row's letter, then fall back to A.

Python has no separate type for a single character. A letter is a string of length 1, such as "A". Two functions convert between letters and numbers. The function ord("A") returns 65, the number that stands for A. The function chr(65) returns "A", the letter for 65. So chr(ord("A") + 2) is "C".

Each row has 2 * i - 1 cells. The cell at position k, counting from 0, is at distance abs(k - (i - 1)) from the middle. The abs function gives the size of a number without its sign, so the distance is never negative. The middle cell shows the row's letter, and each step away from the middle goes one letter back.

Python · editable

The output is:

   A
  ABA
 ABCBA
ABCDCBA

Trace row 4 cell by cell. The outer loop sets i to 4, so the row has seven cells, with k running from 0 to 6. The middle cell is at k equal to 3, which is i - 1. For k equal to 0 the distance is abs(0 - 3), which is 3. The letter is chr(ord("A") + (3 - 3)), which is "A". For k equal to 1 the distance is 2, so the letter is "B". For k equal to 3 the distance is 0, so the letter is "D". The cells on the right mirror the cells on the left, and the row reads ABCDCBA.

The letter pyramid works only while the letters last. Letter 26 is Z. The function chr does not stop at Z, though. It keeps going into the next characters in the table, so chr(ord("A") + 26) returns [. The output below comes from printing 27 letters in a row.

ABCDEFGHIJKLMNOPQRSTUVWXYZ[

No error is raised, so a careless program prints the wrong character without any warning. A program that needs letters should check the count before it starts, with an if statement, as the conditionals lesson shows.

Tracing one centred row by hand

The centred pyramid is easiest to trust when you trace one row on paper before you run the code. Take n equal to 3 and row 2. The outer loop has i equal to 2. The first loop runs n - i, which is 1 time, so it prints one space. The second loop runs 2 * i - 1, which is 3 times, so it prints three stars. The row is ***.

The same trace for each row gives the whole picture for n equal to 3.

Row iSpaces n - iStars 2 * i - 1Printed row
121 *
213 ***
305*****

The spaces shrink by one on each row, and the stars grow by two. Those two movements are the whole shape. If your loops produce a different count on any row, the first row that differs shows you which formula to fix.

Write the counter values beside each step of the trace. The trace takes a minute, and it shows exactly when each loop starts and stops.

Using functions for each row

Each program so far has put the loops at the top level of the file. As programs grow, that becomes hard to read. A function is a named block of code. You define it once with def, and then call it by name as many times as you like.

The line def print_pyramid(n: int) -> None: is the function's header. The name print_pyramid is what you call it by. The n inside the brackets is a parameter, which is a value passed in by the caller. The text : int says that n should be a whole number, and -> None says that the function gives back nothing. Python allows these labels, which are called type hints, but it does not stop a caller from passing the wrong type. The labels are for the reader and for tools that check code.

The next program has two functions, one for a centred pyramid and one for an inverted pyramid. The main part of the program calls both.

Python · editable

The output is:

  *
 ***
*****
*****
 ***
  *

The last two lines of print_pyramid(n) and the first line of print_inverted_pyramid(n) are both five stars, so the output has two full-width rows in the middle. That is correct, but it shows that the two halves are separate pictures. A diamond needs the widest row printed once, and the diamond lesson handles that case.

The second function's outer loop uses range(n, 0, -1), which counts i down from n to 1. So the widest row, with 2 * n - 1 stars and no spaces, prints first. The two functions use the same n, so the two halves always match in size.

Functions also make testing easier. Once print_pyramid works for every size from 1 to 20, you can call it anywhere without checking its loops again. A bug is then in one place, and a fix helps every caller. Programmers call this reuse.

A function that prints but does not return a value gives back None, which is Python's word for nothing. If you print the result of such a call, you see that value.

def print_pyramid(n):
    for i in range(1, n + 1):
        print(" " * (n - i) + "*" * (2 * i - 1))
 
print(print_pyramid(2))

The output is:

 *
***
None

The None comes from print(print_pyramid(2)). The inner call prints the pyramid, then returns None, and the outer print prints that value. A function that you want to use as a value should use return to send back a result, instead of printing it.

What happens when you call a function

When the program reaches print_pyramid(3), it pauses the current code. It creates a new local space for the parameter n and copies the value 3 into it. Then it runs the function body from the top. When the body finishes, the program goes back to the line that made the call, and continues from there. The names n, i and _ exist only while the function runs, so each call starts clean.

Two calls with different values do not interfere. print_pyramid(3) and print_pyramid(5) each have their own n. The i inside print_pyramid and the i at the top level of the file are two different variables, even though they have the same name.

Python keeps a list of the calls that are still running. This list is called the call stack. Each call adds one entry on top, and each return removes one. You will see the stack again in the recursion lesson, where a function calls itself. Python stops a call chain that goes too deep. The limit is 1000 by default on Python 3.14, which you can check with sys.getrecursionlimit().

Common mistakes and their real messages

The file names and paths in the tracebacks below depend on where you save your file, so they will differ on your machine. The last line of each message is what Python printed.

Mistake 1: the spaces are one too many. A common error is to print n - i + 1 spaces instead of n - i. Every row then moves one place to the right. The output for n equal to 3 is:

   *
  ***
 *****

The top row has three spaces, when it needs two. Python does not report this, so the program runs without any warning. The fix is the table: row 1 must have n - 1 spaces, which is 2 for n equal to 3.

Mistake 2: the end of a range is left out. The function range(1, n) stops before n, so it misses the last row. For n equal to 3 the output has only two rows:

  *
 ***

The row of five stars is missing. The fix is to write range(1, n + 1), so that the last number, n, is included.

Mistake 3: a countdown with no step. The number pyramid's right half counts down, and it needs the step -1. Without the step, range(i - 1, 0) is empty when i is greater than 1, because the start is already above the stop and the default step is +1. For row 3 the right half is missing, and the output is 123 instead of 12321.

i = 3
row = ""
for j in range(1, i + 1):
    row += str(j)
for j in range(i - 1, 0):
    row += str(j)
print(row)
123

The fix is range(i - 1, 0, -1). Check the direction of a counter before you choose its range.

Mistake 4: a function name is misspelled. If main calls print_pyramd(3) but the function is called print_pyramid, Python stops with a NameError when it reaches that line:

Traceback (most recent call last):
  File "pattern.py", line 5, in <module>
    print_pyramd(3)
    ^^^^^^^^^^^^
NameError: name 'print_pyramd' is not defined. Did you mean: 'print_pyramid'?

Python suggests the closest name it knows, which is a good hint. Compare the spelling in the definition and in the call.

Mistake 5: a multiplication and a subtraction are in the wrong order. Multiplication happens before subtraction in Python, so " " * n - i is read as (" " * n) - i. A string cannot be subtracted from, and Python says so:

Traceback (most recent call last):
  File "pattern.py", line 3, in <module>
    print(" " * n - i)
          ~~~~~~~~^~~
TypeError: unsupported operand type(s) for -: 'str' and 'int'

The fix is brackets: " " * (n - i). The brackets make the subtraction happen first.

Mistake 6: a number is added to a letter. In the letter pyramid, "A" + k fails when k is a number. Python does not turn the number into a letter for you:

Traceback (most recent call last):
  File "pattern.py", line 2, in <module>
    print("A" + k)
          ~~~~^~~
TypeError: can only concatenate str (not "int") to str

The fix is to turn the letter into a number with ord, do the arithmetic, and turn the result back into a letter with chr: chr(ord("A") + k).

Mistake 7: the line break is missing. If the row's print() is left out, or if the stars are printed with end="" and no print() follows, every row runs into the next. Three rows of two stars each, printed with end="" and no print() after them, give one long line:

******

The fix is one print() after the inner loops, at the same indentation as the loops.

Mistake 8: a syntax error stops the whole file. Python checks the whole file before it runs any of it. These mistakes stop the program at once, and no output is printed.

A missing colon at the end of a for line gives:

  File "pattern.py", line 2
    for i in range(1, n + 1)
                            ^
SyntaxError: expected ':'

A block that is not indented gives:

  File "pattern.py", line 3
    print("*")
    ^^^^^
IndentationError: expected an indented block after 'for' statement on line 2

The fix for both is to read the line named in the message. The first mistake is a missing colon, and the second is a line that should be indented under the for.

Debugging walkthrough: a pyramid leans to one side

Suppose you write a centred pyramid for n equal to 3, and the output comes out like this:

   *
  ***
 *****

The stars in each row are right, but every row starts one place too far to the right. The top row has three spaces, and the bottom row has one. You wanted two, one and zero. Something is wrong with the spaces.

Step 1: count the spaces on the first and last rows. The top row has three, and the last row has one. The correct counts are two and zero. The space count is one too many on every row.

Step 2: look at the space loop. If it reads range(n - i + 1), you have the wrong formula. With i equal to 1 that gives 3 spaces, and with i equal to 3 it gives 1 space. The formula you need is range(n - i).

Step 3: fix the loop and run the program again. The top row now has 2 spaces, the middle row has 1 space, and the bottom row has none. The picture is centred.

Step 4: check the stars too. The top row has one star and the bottom row has five. For n equal to 3 that is 2 * 1 - 1 and 2 * 3 - 1, which are correct. The picture now matches the table.

A useful habit is to check the smallest size first. For n equal to 1 the pyramid is one star. For n equal to 2 it is a star with one space in front, then three stars with no space. If n equal to 2 is right, the formulas are probably right for every size. A bug that appears only at larger sizes is usually in code that depends on the size, such as the digit count in a number pyramid or the letter count in a letter pyramid.

Variations and edge cases

For n equal to 1 every pyramid prints a single symbol. The centred pyramid prints one star, the inverted pyramid prints one star, the number pyramid prints one 1, and the letter pyramid prints one A. Check this size first, because the formulas often break at this size.

For n equal to 0 the loops run zero times, and nothing is printed. A program that prints an empty line for zero rows has a print() outside the loop. Look for it if the output has an unexpected blank line.

A pyramid can be made hollow, so that only the edge of each row is a star. That is the subject of the hollow lesson. The idea is to add an if statement inside the star loop, and choose between a star and a space by checking the position of the cell.

A pyramid can use any symbol. Replace "*" with str(i), and each row becomes copies of its own row number. For n equal to 4 the rows are 1, 222, 33333 and 4444444.

Interview questions and real uses

Pyramid questions in interviews often come with a twist. You might be asked to print the pyramid for any n, to use numbers, to use letters, or to print the inverted version without rewriting the code. Each twist changes one part of the row, and the rest stays the same. A strong answer shows that you see the row as two parts, spaces and symbols, and that you can change one part without touching the other.

A typical question is to write a function that prints a centred pyramid for a given n, and then to call it with n equal to 5. A good answer starts with the table, writes the function, and then calls it. The interviewer wants to hear the reasons: "Each row has n - i spaces and 2 * i - 1 stars, so I put those in two loops inside one function. The main part of the program only calls the function."

Pyramid shapes appear outside programming too. A bar chart that grows from the middle, a stack of boxes in a warehouse, and a centred title in a document all have a row of fixed width, with a part that changes size on each line.

Practice

Try each exercise before you open its answer. Write the program, and trace it by hand with a small n first.

  1. Print a centred star pyramid with n equal to 5. Predict the bottom row before you run the program. How many stars does it have?

    Show the answer

    The bottom row has nine stars, because 2 * 5 - 1 is 9, and no spaces, because 5 - 5 is 0. Use the centred program from worked example 1 and change n to 5.

  2. Print an inverted pyramid with n equal to 3. Write the table of spaces and stars first. What is the widest row?

    Show the answer

    The output is *****, then ***, then *. The widest row is the first one, with five stars and no spaces. Use the inverted program from worked example 2 and change n to 3.

  3. Print the number pyramid for n equal to 3. Predict the middle digit of each row before you run it.

    Show the answer

    The output is 1, then 121, then 12321. The middle digit of each row is its row number: 1, 2 and 3. Use the number pyramid program from worked example 3 and change n to 3.

  4. Print the letter pyramid for n equal to 3. Trace row 3 cell by cell before you run it.

    Show the answer

    The output is A, then ABA, then ABCBA. In row 3 the middle cell is at k equal to 2, so its letter is chr(ord("A") + 2), which is C. The cells on either side are B, and the outer cells are A. Use the program from worked example 4 and change n to 3.

  5. Print a centred pyramid where row i shows the digit i repeated 2 * i - 1 times. Write the output for n equal to 4 on paper first, then write the code.

    Show the answer

    The output for n equal to 4 is 1, then 222, then 33333, then 4444444. Each row uses the centred loops from the star pyramid, with str(i) printed in place of the star. Row 2 is two spaces and three copies of 2.

  6. Write two functions, print_spaces(count) and print_stars(count). Each prints the given number of characters on one line, with no line break. Then write print_centred_row(n, i), which calls the other two to print row i of a pyramid with n rows, and ends the row with a line break. Call it in a loop from the main part of the program.

    Show the answer

    print_spaces loops count times and prints a space with end="". print_stars loops count times and prints a star. print_centred_row calls print_spaces(n - i), then print_stars(2 * i - 1), then print(). The loop at the bottom runs i from 1 to n and calls print_centred_row(n, i) each time. The output is the centred pyramid from worked example 1.

  7. A program is meant to print a centred pyramid for n equal to 3, but it prints three rows where the top row has three spaces. The space loop is for _ in range(n - i + 1):. What is the fix?

    Show the answer

    The space count is one too many. With n - i + 1 the top row gets three spaces instead of two, and every row is pushed one place to the right. Change the loop to range(n - i). The top row then has two spaces and the bottom row has none.

  8. Predict the output for n equal to 1 and for n equal to 0, for both the centred pyramid and the inverted pyramid. Write your answers before you run the programs.

    Show the answer

    For n equal to 1, both pyramids print one star on one line. For n equal to 0, both print nothing, because range(1, 1) is empty, and range(0, 0, -1) is also empty. If your program prints a blank line for n equal to 0, you have a print() outside the loop.

  9. Print the number pyramid for n equal to 9. Predict the last row before you run it. Hint: it is the digits 1 to 9, then the digits 8 down to 1.

    Show the answer

    The last row is 12345678987654321. It has no leading spaces, because 9 - 9 is 0. The row has 17 digits, which is 2 * 9 - 1, so the row matches the star pyramid.

  10. Predict the last row of the number pyramid for n equal to 10. Then run the program and check your prediction. Explain why the row no longer lines up with the rows above it.

    Show the answer

    The last row is 12345678910987654321. The number 10 has two characters, so the row is 20 characters long, not 19. The pattern is still printed correctly, but the row is wider than the pattern expects. To keep the picture tidy, format each number to a fixed width, or keep n at 9 or less.

What you now know

  • A pyramid row has two parts: spaces on the left and symbols in the middle. Give each part its own loop, or build the row as one string.
  • For a centred pyramid, row i has n - i spaces and 2 * i - 1 stars. The inverted version reverses the order of the rows.
  • A number pyramid counts up to the row number and then back down, using a range with a step of -1 for the way down.
  • A letter pyramid picks each letter from its distance to the middle cell, using abs, ord and chr.
  • A function is a named block of code. It takes parameters, runs its own loops, and returns to the caller. Split a long program into functions, one for each job.
  • Check every pyramid on the first row, the last row and the total number of symbols, and test n equal to 1 and n equal to 0 before you trust the output.
Practice this topic: coding problems for Pattern Printing →

Stuck? Ask the tutor

Ask about anything in this lesson. Answers are short and use simple words.

Sign in to ask the tutor.

← Number and alphabet patterns in Python