How to make a rectangle in Python
Learn how to create a rectangle in Python with various methods. Discover tips, real-world uses, and how to debug common errors.

You can draw rectangles in Python for graphics and game development. Various libraries help you accomplish this, each with unique methods to define shapes and their properties.
In this article, we'll cover several techniques to create rectangles. You'll find practical tips, explore real-world applications, and get advice to debug your code so your shapes render perfectly.
Using asterisks to print a rectangle
width = 10
height = 4
for i in range(height):
print('*' * width)--OUTPUT--**********
**********
**********
**********
This method creates a simple rectangle in your terminal. The for loop iterates a number of times equal to the height variable. In each iteration, Python's string multiplication operator is used. The expression '*' * width creates a new string containing the asterisk character repeated width times.
The print() function then outputs this string of asterisks to a new line. Repeating this process for each value in the range(height) effectively stacks these lines, drawing a solid rectangle made of characters.
Basic rectangle implementations
That simple print method is great for a quick result, but you can achieve more complex and graphical rectangles using different programming structures.
Using nested loops for a rectangle pattern
width, height = 8, 3
for i in range(height):
for j in range(width):
print('*', end='')
print()--OUTPUT--********
********
********
This approach uses a nested loop structure where the outer loop manages the rows and the inner loop handles the columns. This gives you more granular control over the rectangle's construction compared to string multiplication.
- The inner loop's
print('*', end='')statement is the key. It prints a single asterisk and theend=''argument prevents the cursor from moving to a new line. - Once the inner loop completes a full row of asterisks, the outer loop's final
print()statement executes. This moves the cursor down, starting the next row of the rectangle.
Creating a Rectangle class
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
rect = Rectangle(5, 3)
print(f"Rectangle area: {rect.area()}")--OUTPUT--Rectangle area: 15
Creating a Rectangle class is a powerful object-oriented approach. It bundles data (like width and height) and functions that operate on that data (like an area() method) into a single, reusable blueprint. This keeps your code organized and intuitive.
- The special
__init__method is the constructor. It runs when you create a newRectangleobject, assigning the providedwidthandheightvalues to the instance. - Methods like
area()can then access these stored values usingselfto perform calculations specific to that rectangle instance.
Drawing rectangles with Turtle graphics
import turtle
t = turtle.Turtle()
for _ in range(2):
t.forward(100) # Width
t.left(90)
t.forward(50) # Height
t.left(90)
turtle.done()--OUTPUT--[Turtle graphics window with a rectangle]
The turtle library offers a simple, visual way to draw shapes. You start by creating a turtle.Turtle() object, which acts like a pen on a digital canvas. The for loop then executes its block of code twice to complete the rectangle.
- The turtle moves forward with
t.forward()to draw a side, then turns 90 degrees usingt.left(90). - Repeating this sequence draws the four sides of the rectangle. Finally,
turtle.done()keeps the window open so you can see your creation.
Graphical rectangle implementations
While turtle offers a fun introduction to drawing, libraries like matplotlib, Pygame, and tkinter provide robust tools for more advanced graphical applications.
Creating rectangles with matplotlib
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
fig, ax = plt.subplots()
ax.add_patch(Rectangle((0.2, 0.2), 0.6, 0.4,
edgecolor='blue', facecolor='lightblue'))
plt.axis([0, 1, 0, 1])
plt.show()--OUTPUT--[Matplotlib window showing a blue rectangle]
The matplotlib library is a go-to for plotting data, but it’s also great for drawing shapes. You start by creating a figure and axes with plt.subplots(), which sets up your drawing canvas. The key is to import the Rectangle class from matplotlib.patches.
- You define a rectangle with its bottom-left xy-coordinate, width, and height, then add it to your plot using
ax.add_patch(). - You can also specify visual properties like
edgecolorandfacecolorto style your shape.
Finally, plt.show() renders the plot in a new window.
Drawing rectangles with Pygame
import pygame
pygame.init()
screen = pygame.display.set_mode((400, 300))
pygame.draw.rect(screen, (255, 0, 0), (100, 50, 200, 150))
pygame.display.flip()
pygame.time.wait(3000)
pygame.quit()--OUTPUT--[Pygame window with a red rectangle]
Pygame is a go-to library for game development, offering simple functions for graphics. After initializing Pygame with pygame.init(), you create a display window, which acts as your canvas.
- The core function is
pygame.draw.rect(). It draws the shape onto the screen surface you created. - You define the rectangle's appearance with two tuples: one for the color in RGB format and another for its position and dimensions
(x, y, width, height). - Finally,
pygame.display.flip()makes your drawing visible by updating the entire screen.
Creating rectangles with tkinter
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
canvas.create_rectangle(50, 50, 250, 150, fill="green")
root.mainloop()--OUTPUT--[Tkinter window with a green rectangle]
The tkinter library is Python's standard toolkit for building graphical user interfaces. You first set up a main window with tk.Tk() and place a Canvas widget inside it to serve as your drawing surface. The canvas.pack() method then makes this widget visible.
- The actual drawing happens with the
canvas.create_rectangle()method. - This function defines the rectangle using two coordinate pairs: the top-left corner and the bottom-right corner.
- You can customize its appearance using options like
fillto set the color.
Finally, root.mainloop() starts the application, displaying the window and its contents until you close it.
Move faster with Replit
Replit is an AI-powered development platform where Python dependencies come pre-installed, so you can skip the setup and start coding instantly. This lets you move from piecing together individual techniques to building complete applications with Agent 4. Describe the app you want to build, and the Agent will take it from an idea to a working product.
Instead of just drawing shapes, you can build:
- A data visualization tool that uses
matplotlib.patches.Rectangleto generate bar charts for financial reports. - A simple 2D game built with
pygamewhere players control a rectangular paddle to hit a ball. - A GUI layout planner that lets users draw and resize rectangles with
tkinterto design a user interface.
Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.
Common errors and challenges
Drawing rectangles can sometimes lead to tricky bugs, but understanding the common pitfalls makes them much easier to fix.
Fixing off-by-one errors when drawing hollow rectangles
When using loops to draw a hollow rectangle, you might encounter off-by-one errors. These bugs typically happen because the loop's range or the boundary-checking logic is incorrect by a single step, causing distorted or incomplete borders.
- A common mistake is forgetting that indices are zero-based. If a rectangle has a
widthof 10, its column indices run from 0 to 9. Your condition to check for the right-side border should bej == width - 1, notj == width. - Double-check your loop conditions. An expression like
range(height)correctly iterates from0toheight - 1. Miscalculating this range can cut off the bottom or right side of your rectangle.
Debugging dimension updates in the Rectangle class
When you create a Rectangle class, you might find that its properties don't update as expected. For instance, if you change an object's width after it has been created, any methods that rely on it must be designed to use the new value.
- If your
area()method simply returnsself.width * self.height, it will always calculate the area using the current dimensions. This is good. - However, if you calculated the area once in the
__init__method and stored it as an attribute likeself.area, this value would become stale ifself.widthorself.heightwere changed later. The fix is to always recalculate dependent properties within their respective methods.
Handling overlapping conditions in collision detection
In game development with libraries like Pygame, checking if two rectangles overlap is a fundamental task for collision detection. The logic can be surprisingly tricky, and it's easy to write conditions that miss certain scenarios of overlap.
- A robust approach is to check for all the ways two rectangles can not overlap. If none of these non-overlapping conditions are true, the rectangles must be colliding.
- Two rectangles (A and B) do not overlap if: A is entirely to the right of B, A is entirely to the left of B, A is entirely above B, or A is entirely below B. Testing for these four simple conditions is much more reliable than trying to define every possible way they could intersect.
Fixing off-by-one errors when drawing hollow rectangles
Drawing a hollow rectangle with loops is a classic spot for off-by-one errors, which often cause missing borders. This happens when a boundary check is slightly off. The code below shows how a condition like i == height fails to render correctly.
def draw_hollow_rectangle(width, height):
for i in range(height):
if i == 0 or i == height: # Bug: i will never equal height
print('*' * width)
else:
print('*' + ' ' * (width-2) + '*')
draw_hollow_rectangle(6, 4) # Bottom border missing
The range(height) function stops one number short of height, so the loop variable i can never satisfy the i == height condition. This is why the bottom border is missing. Take a look at the corrected code.
def draw_hollow_rectangle(width, height):
for i in range(height):
if i == 0 or i == height-1: # Fixed: height-1 is the last row
print('*' * width)
else:
print('*' + ' ' * (width-2) + '*')
draw_hollow_rectangle(6, 4) # All borders visible
The fix is simple yet crucial. The condition is changed from i == height to i == height - 1. This works because a loop defined with range(height) iterates from 0 up to, but not including, height. Therefore, the last row's index is always height - 1. It's a classic off-by-one error, so always double-check your boundary conditions when working with loops and zero-based indices to ensure your shapes render correctly.
Debugging dimension updates in the Rectangle class
When you build a Rectangle class, it's easy to create a bug where its properties don't update. If the area is calculated just once in the __init__ method, it becomes a static value that won't change with the dimensions.
The code below shows this exact problem—the width is updated, but the area remains the same.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height # Bug: area isn't updated when dimensions change
rect = Rectangle(5, 3)
rect.width = 10 # Changed the width
print(f"Rectangle area: {rect.area}") # Still shows old area: 15
The issue is that self.area is set just once inside the __init__ constructor. When you later change self.width, the original area value remains, leading to a stale result. Check out the corrected approach below.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
return self.width * self.height # Calculated dynamically
rect = Rectangle(5, 3)
rect.width = 10 # Changed the width
print(f"Rectangle area: {rect.area}") # Correctly shows updated area: 30
The fix is to make area a property that calculates its value dynamically. By using the @property decorator, the area method is treated like an attribute, so you can still call it with rect.area. Now, every time it's accessed, the expression self.width * self.height is re-evaluated. This ensures the area always reflects the current dimensions. Watch for this when one class attribute's value depends on another; dynamic properties are often the answer.
Handling overlapping conditions in collision detection
Another common collision task is checking if a point is inside a rectangle. The logic for boundary checks is strict, and using the wrong operator like or instead of and can cause bugs. The code below contains this exact error.
def is_inside_rectangle(point_x, point_y, rect):
# Bug: incorrectly uses OR instead of AND for boundary check
return (point_x >= rect['x'] or
point_x <= rect['x'] + rect['width'] or
point_y >= rect['y'] or
point_y <= rect['y'] + rect['height'])
point = (15, 25)
rectangle = {'x': 10, 'y': 20, 'width': 30, 'height': 40}
print(f"Point is inside: {is_inside_rectangle(point[0], point[1], rectangle)}")
The logical error here is the use of the or operator. This makes the check far too lenient, returning True for points outside the rectangle. A point must satisfy all boundary conditions. See the corrected implementation below.
def is_inside_rectangle(point_x, point_y, rect):
# Fixed: using AND to check all boundaries are satisfied
return (point_x >= rect['x'] and
point_x <= rect['x'] + rect['width'] and
point_y >= rect['y'] and
point_y <= rect['y'] + rect['height'])
point = (15, 25)
rectangle = {'x': 10, 'y': 20, 'width': 30, 'height': 40}
print(f"Point is inside: {is_inside_rectangle(point[0], point[1], rectangle)}")
The fix replaces the faulty or operators with and. For a point to be inside a rectangle, it must meet all four boundary conditions at once—it can't just satisfy one. Using and ensures the check is strict. This kind of logical error is common in collision detection for games or hit-testing in GUIs, so always double-check your boolean operators when defining spatial boundaries.
Real-world applications
With a solid grasp on drawing and debugging rectangles, you can build practical features like text-based UIs and game collision systems.
Creating a simple text-based UI with the draw_textbox function
The draw_textbox function encapsulates the logic for printing a bordered box, making it easy to create structured elements for a text-based user interface.
def draw_textbox(width, height, title=""):
print("+" + "-" * (width-2) + "+")
if title:
print(f"|{title.center(width-2)}|")
print("+" + "-" * (width-2) + "+")
for _ in range(height-3 if title else height-2):
print("|" + " " * (width-2) + "|")
print("+" + "-" * (width-2) + "+")
draw_textbox(20, 6, "Main Menu")
The draw_textbox function constructs a text box using string multiplication and conditional logic. It prints the top and bottom borders using + for corners and - for lines. The width calculation, width-2, accounts for the two corner characters on each line.
- If you provide a
title, it’s automatically centered using the.center()method and separated by an extra horizontal line. - A ternary operator inside the
forloop’s range,height-3 if title else height-2, dynamically adjusts the box’s empty space to maintain the correct overall height.
Implementing collision detection with the collides_with method
You can implement this collision logic directly within a class, creating a collides_with method to cleanly determine if two rectangular objects intersect.
class GameRectangle:
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height
def collides_with(self, other):
return (self.x < other.x + other.width and
self.x + self.width > other.x and
self.y < other.y + other.height and
self.y + self.height > other.y)
player = GameRectangle(10, 10, 5, 5)
obstacle = GameRectangle(12, 12, 6, 6)
print(f"Collision detected: {player.collides_with(obstacle)}")
The GameRectangle class acts as a blueprint for game objects, storing their position (x, y) and size. Its collides_with method is the key to detecting intersections. This method checks if two rectangles overlap by testing for overlap on both the horizontal and vertical axes at the same time.
- The first two conditions confirm the rectangles overlap on the x-axis.
- The last two conditions confirm they overlap on the y-axis.
A collision is only registered if all four conditions are met, which is enforced by the and operator. This ensures there's no gap between the objects on either axis.
Get started with Replit
Now, turn these techniques into a real tool with Replit Agent. Try prompts like "build a GUI layout planner with tkinter" or "create a simple collision detection game with Pygame."
The Agent writes the code, tests for errors, and deploys your application directly from your browser. Start building with Replit.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

.png)

.png)